WIP simplify

This commit is contained in:
2026-01-29 09:38:41 +01:00
parent f1f1b28b31
commit 4d0d837e14
11 changed files with 434 additions and 291 deletions

View File

@@ -1,14 +1,19 @@
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::time::Instant;
use rand::rngs::StdRng;
use rand::SeedableRng;
use ratatui::layout::{Alignment, Constraint, Layout, Rect};
use ratatui::style::{Color, Modifier, Style};
use ratatui::text::{Line, Span};
use ratatui::widgets::{Block, Borders, Cell, Clear, Paragraph, Row, Table};
use ratatui::Frame;
use cagire_forth::Forth;
use crate::app::App;
use crate::engine::{LinkState, SequencerSnapshot};
use crate::model::SourceSpan;
use crate::model::{SourceSpan, StepContext, Value};
use crate::page::Page;
use crate::state::{FlashKind, Modal, PanelFocus, PatternField, SidePanel};
use crate::views::highlight::{self, highlight_line, highlight_line_with_runtime};
@@ -20,6 +25,64 @@ use super::{
dict_view, engine_view, help_view, main_view, options_view, patterns_view, title_view,
};
fn compute_stack_display(lines: &[String], editor: &cagire_ratatui::Editor) -> String {
let cursor_line = editor.cursor().0;
let partial: Vec<&str> = lines.iter().take(cursor_line + 1).map(|s| s.as_str()).collect();
let script = partial.join("\n");
if script.trim().is_empty() {
return "Stack: []".to_string();
}
let vars = Arc::new(Mutex::new(HashMap::new()));
let dict = Arc::new(Mutex::new(HashMap::new()));
let rng = Arc::new(Mutex::new(StdRng::seed_from_u64(42)));
let forth = Forth::new(vars, dict, rng);
let ctx = StepContext {
step: 0,
beat: 0.0,
bank: 0,
pattern: 0,
tempo: 120.0,
phase: 0.0,
slot: 0,
runs: 0,
iter: 0,
speed: 1.0,
fill: false,
nudge_secs: 0.0,
};
match forth.evaluate(&script, &ctx) {
Ok(_) => {
let stack = forth.stack();
let formatted: Vec<String> = stack.iter().map(format_value).collect();
format!("Stack: [{}]", formatted.join(" "))
}
Err(e) => format!("Error: {e}"),
}
}
fn format_value(v: &Value) -> String {
match v {
Value::Int(n, _) => n.to_string(),
Value::Float(f, _) => {
if f.fract() == 0.0 && f.abs() < 1_000_000.0 {
format!("{f:.1}")
} else {
format!("{f:.4}")
}
}
Value::Str(s, _) => format!("\"{s}\""),
Value::Quotation(..) => "[...]".to_string(),
Value::CycleList(items) => {
let inner: Vec<String> = items.iter().map(format_value).collect();
format!("({})", inner.join(" "))
}
}
}
fn adjust_spans_for_line(
spans: &[SourceSpan],
line_start: usize,
@@ -619,28 +682,24 @@ fn render_modal(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, term
let show_search = app.editor_ctx.editor.search_active()
|| !app.editor_ctx.editor.search_query().is_empty();
let (search_area, editor_area, hint_area) = if show_search {
let search_area = Rect::new(inner.x, inner.y, inner.width, 1);
let editor_area = Rect::new(
inner.x,
inner.y + 1,
inner.width,
inner.height.saturating_sub(2),
);
let hint_area =
Rect::new(inner.x, inner.y + 1 + editor_area.height, inner.width, 1);
(Some(search_area), editor_area, hint_area)
let reserved_lines = 1 + if show_search { 1 } else { 0 };
let editor_height = inner.height.saturating_sub(reserved_lines);
let mut y = inner.y;
let search_area = if show_search {
let area = Rect::new(inner.x, y, inner.width, 1);
y += 1;
Some(area)
} else {
let editor_area = Rect::new(
inner.x,
inner.y,
inner.width,
inner.height.saturating_sub(1),
);
let hint_area = Rect::new(inner.x, inner.y + editor_area.height, inner.width, 1);
(None, editor_area, hint_area)
None
};
let editor_area = Rect::new(inner.x, y, inner.width, editor_height);
y += editor_height;
let hint_area = Rect::new(inner.x, y, inner.width, 1);
if let Some(sa) = search_area {
let style = if app.editor_ctx.editor.search_active() {
Style::default().fg(Color::Yellow)
@@ -671,32 +730,52 @@ fn render_modal(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, term
let dim = Style::default().fg(Color::DarkGray);
let key = Style::default().fg(Color::Yellow);
let hint = if app.editor_ctx.editor.search_active() {
Line::from(vec![
if app.editor_ctx.editor.search_active() {
let hint = Line::from(vec![
Span::styled("Enter", key),
Span::styled(" confirm ", dim),
Span::styled("Esc", key),
Span::styled(" cancel", dim),
]);
frame.render_widget(Paragraph::new(hint).alignment(Alignment::Right), hint_area);
} else if app.editor_ctx.show_stack {
let stack_text = compute_stack_display(text_lines, &app.editor_ctx.editor);
let hint = Line::from(vec![
Span::styled("Esc", key),
Span::styled(" save ", dim),
Span::styled("C-e", key),
Span::styled(" eval ", dim),
Span::styled("C-k", key),
Span::styled(" hide", dim),
]);
let [hint_left, stack_right] = Layout::horizontal([
Constraint::Length(hint.width() as u16),
Constraint::Fill(1),
])
.areas(hint_area);
frame.render_widget(Paragraph::new(hint), hint_left);
frame.render_widget(
Paragraph::new(Span::styled(stack_text, dim)).alignment(Alignment::Right),
stack_right,
);
} else {
Line::from(vec![
let hint = Line::from(vec![
Span::styled("Esc", key),
Span::styled(" save ", dim),
Span::styled("C-e", key),
Span::styled(" eval ", dim),
Span::styled("C-f", key),
Span::styled(" find ", dim),
Span::styled("C-n", key),
Span::styled("/", dim),
Span::styled("C-p", key),
Span::styled(" next/prev ", dim),
Span::styled("C-k", key),
Span::styled(" stack ", dim),
Span::styled("C-u", key),
Span::styled("/", dim),
Span::styled("C-r", key),
Span::styled(" undo/redo", dim),
])
};
frame.render_widget(Paragraph::new(hint).alignment(Alignment::Right), hint_area);
]);
frame.render_widget(Paragraph::new(hint).alignment(Alignment::Right), hint_area);
}
}
Modal::PatternProps {
bank,