Monster commit: native version

This commit is contained in:
2026-01-30 15:03:49 +01:00
parent c2e6dfe88b
commit 44d1e9af24
35 changed files with 1491 additions and 366 deletions

View File

@@ -1,5 +1,5 @@
use ratatui::layout::{Constraint, Layout, Rect};
use ratatui::style::{Color, Modifier, Style};
use ratatui::style::{Modifier, Style};
use ratatui::text::{Line as RLine, Span};
use ratatui::widgets::{Block, Borders, List, ListItem, Paragraph};
use ratatui::Frame;
@@ -7,6 +7,7 @@ use ratatui::Frame;
use crate::app::App;
use crate::model::{Word, WORDS};
use crate::state::DictFocus;
use crate::theme::{dict, search};
const CATEGORIES: &[&str] = &[
// Forth core
@@ -61,10 +62,10 @@ fn render_header(frame: &mut Frame, area: Rect) {
pushes 7. This page lists all words with their signature ( inputs -- outputs ).";
let block = Block::default()
.borders(Borders::ALL)
.border_style(Style::new().fg(Color::Rgb(60, 60, 70)))
.border_style(Style::new().fg(dict::BORDER_NORMAL))
.title("Dictionary");
let para = Paragraph::new(desc)
.style(Style::new().fg(Color::Rgb(140, 145, 155)))
.style(Style::new().fg(dict::HEADER_DESC))
.wrap(Wrap { trim: false })
.block(block);
frame.render_widget(para, area);
@@ -79,20 +80,20 @@ fn render_categories(frame: &mut Frame, app: &App, area: Rect, dimmed: bool) {
.map(|(i, name)| {
let is_selected = i == app.ui.dict_category;
let style = if dimmed {
Style::new().fg(Color::Rgb(80, 80, 90))
Style::new().fg(dict::CATEGORY_DIMMED)
} else if is_selected && focused {
Style::new().fg(Color::Yellow).add_modifier(Modifier::BOLD)
Style::new().fg(dict::CATEGORY_FOCUSED).add_modifier(Modifier::BOLD)
} else if is_selected {
Style::new().fg(Color::Cyan)
Style::new().fg(dict::CATEGORY_SELECTED)
} else {
Style::new().fg(Color::White)
Style::new().fg(dict::CATEGORY_NORMAL)
};
let prefix = if is_selected && !dimmed { "> " } else { " " };
ListItem::new(format!("{prefix}{name}")).style(style)
})
.collect();
let border_color = if focused { Color::Yellow } else { Color::Rgb(60, 60, 70) };
let border_color = if focused { dict::BORDER_FOCUSED } else { dict::BORDER_NORMAL };
let block = Block::default()
.borders(Borders::ALL)
.border_style(Style::new().fg(border_color))
@@ -142,12 +143,12 @@ fn render_words(frame: &mut Frame, app: &App, area: Rect, is_searching: bool) {
let mut lines: Vec<RLine> = Vec::new();
for word in &words {
let name_bg = Color::Rgb(40, 50, 60);
let name_bg = dict::WORD_BG;
let name_style = Style::new()
.fg(Color::Green)
.fg(dict::WORD_NAME)
.bg(name_bg)
.add_modifier(Modifier::BOLD);
let alias_style = Style::new().fg(Color::DarkGray).bg(name_bg);
let alias_style = Style::new().fg(dict::ALIAS).bg(name_bg);
let name_text = if word.aliases.is_empty() {
format!(" {}", word.name)
} else {
@@ -167,19 +168,19 @@ fn render_words(frame: &mut Frame, app: &App, area: Rect, is_searching: bool) {
]));
}
let stack_style = Style::new().fg(Color::Magenta);
let stack_style = Style::new().fg(dict::STACK_SIG);
lines.push(RLine::from(vec![
Span::raw(" "),
Span::styled(word.stack.to_string(), stack_style),
]));
let desc_style = Style::new().fg(Color::White);
let desc_style = Style::new().fg(dict::DESCRIPTION);
lines.push(RLine::from(vec![
Span::raw(" "),
Span::styled(word.desc.to_string(), desc_style),
]));
let example_style = Style::new().fg(Color::Rgb(120, 130, 140));
let example_style = Style::new().fg(dict::EXAMPLE);
lines.push(RLine::from(vec![
Span::raw(" "),
Span::styled(format!("e.g. {}", word.example), example_style),
@@ -205,7 +206,7 @@ fn render_words(frame: &mut Frame, app: &App, area: Rect, is_searching: bool) {
let category = CATEGORIES[app.ui.dict_category];
format!("{category} ({} words)", words.len())
};
let border_color = if focused { Color::Yellow } else { Color::Rgb(60, 60, 70) };
let border_color = if focused { dict::BORDER_FOCUSED } else { dict::BORDER_NORMAL };
let block = Block::default()
.borders(Borders::ALL)
.border_style(Style::new().fg(border_color))
@@ -216,9 +217,9 @@ fn render_words(frame: &mut Frame, app: &App, area: Rect, is_searching: bool) {
fn render_search_bar(frame: &mut Frame, app: &App, area: Rect) {
let style = if app.ui.dict_search_active {
Style::new().fg(Color::Yellow)
Style::new().fg(search::ACTIVE)
} else {
Style::new().fg(Color::DarkGray)
Style::new().fg(search::INACTIVE)
};
let cursor = if app.ui.dict_search_active { "_" } else { "" };
let text = format!(" /{}{}", app.ui.dict_search_query, cursor);