fixed the multi-line note and some utf-8 stuff

This commit is contained in:
Hermes Agent
2026-08-16 19:42:44 +00:00
parent ba530a7271
commit b099157a17
5 changed files with 206 additions and 10 deletions

View File

@@ -503,17 +503,40 @@ fn draw_overlay(frame: &mut Frame<'_>, app: &App) {
}
Mode::Input(input) => {
let h = if input.multiline { 18 } else { 7 };
let area = center(frame.area(), 78, h);
let inner = area.inner(Margin {
horizontal: 1,
vertical: 1,
});
let before_cursor = &input.value[..input.cursor];
let cursor_line = before_cursor.bytes().filter(|byte| *byte == b'\n').count();
let current_line_start = before_cursor.rfind('\n').map_or(0, |index| index + 1);
let cursor_column = Line::from(&before_cursor[current_line_start..]).width();
let vertical_scroll =
cursor_line.saturating_sub(inner.height.saturating_sub(1) as usize);
let horizontal_scroll =
cursor_column.saturating_sub(inner.width.saturating_sub(1) as usize);
let shown = if input.value.is_empty() {
Span::styled("Type here…", Style::default().fg(Color::DarkGray))
Text::from(Line::from(Span::styled(
"Type here…",
Style::default().fg(Color::DarkGray),
)))
} else {
Span::raw(input.value.clone())
Text::from(input.value.as_str())
};
popup(
frame,
center(frame.area(), 78, h),
area,
&input.title,
Paragraph::new(Line::from(shown)).wrap(Wrap { trim: false }),
Paragraph::new(shown).scroll((
vertical_scroll.min(u16::MAX as usize) as u16,
horizontal_scroll.min(u16::MAX as usize) as u16,
)),
);
frame.set_cursor_position((
inner.x + cursor_column.saturating_sub(horizontal_scroll) as u16,
inner.y + cursor_line.saturating_sub(vertical_scroll) as u16,
));
}
Mode::Properties(p) => {
let names = [
@@ -841,7 +864,11 @@ fn center(area: Rect, width: u16, height: u16) -> Rect {
mod tests {
use super::*;
use crate::{app::App, db::Database, model::ItemChanges};
use ratatui::{Terminal, backend::TestBackend};
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use ratatui::{
Terminal,
backend::{Backend, TestBackend},
};
use tempfile::tempdir;
#[test]
fn renders_main_workspace() {
@@ -932,4 +959,51 @@ mod tests {
assert!(screen.contains("Compact item"));
assert!(screen.contains("When"));
}
#[test]
fn note_editor_renders_and_saves_entered_line_breaks() {
let d = tempdir().unwrap();
let p = d.path().join("notes.agnd");
let mut db = Database::open(&p).unwrap();
db.add_item("Write release notes").unwrap();
let mut app = App::new(db, p).unwrap();
app.handle_key(KeyEvent::new(KeyCode::F(5), KeyModifiers::NONE))
.unwrap();
for c in "first line".chars() {
app.handle_key(KeyEvent::new(KeyCode::Char(c), KeyModifiers::NONE))
.unwrap();
}
app.handle_key(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE))
.unwrap();
for c in "second line".chars() {
app.handle_key(KeyEvent::new(KeyCode::Char(c), KeyModifiers::NONE))
.unwrap();
}
let backend = TestBackend::new(100, 30);
let mut term = Terminal::new(backend).unwrap();
term.draw(|frame| draw(frame, &mut app)).unwrap();
let cursor = term.backend_mut().get_cursor_position().unwrap();
let rows = term
.backend()
.buffer()
.content
.chunks(100)
.map(|row| row.iter().map(|cell| cell.symbol()).collect::<String>())
.collect::<Vec<_>>();
let first_row = rows
.iter()
.position(|row| row.contains("first line"))
.unwrap();
let second_row = rows
.iter()
.position(|row| row.contains("second line"))
.unwrap();
assert_eq!(second_row, first_row + 1);
assert_eq!(cursor.y as usize, second_row);
app.handle_key(KeyEvent::new(KeyCode::Char('s'), KeyModifiers::CONTROL))
.unwrap();
assert_eq!(app.items[0].note, "first line\nsecond line");
}
}