From b72611d6bba446e2c714244fe950e9adf41cbe8d Mon Sep 17 00:00:00 2001 From: Denis Olehov Date: Fri, 2 Jan 2026 19:39:34 +0100 Subject: [PATCH] feat: add asciiscript implementation --- src-tauri/Cargo.toml | 2 +- src-tauri/src/asciiscript/ast.rs | 297 ++++ src-tauri/src/asciiscript/lexer.rs | 867 ++++++++++ src-tauri/src/asciiscript/mod.rs | 17 + src-tauri/src/asciiscript/parser.rs | 1507 +++++++++++++++++ src-tauri/src/asciiscript/render.rs | 1078 ++++++++++++ ..._lib__asciiscript__tests__alert_error.snap | 7 + ...t_lib__asciiscript__tests__alert_info.snap | 7 + ...ib__asciiscript__tests__alert_warning.snap | 7 + ...__asciiscript__tests__alert_with_code.snap | 8 + ...ipt__tests__alert_with_multiple_lines.snap | 9 + ...t_lib__asciiscript__tests__box_titled.snap | 9 + ...ciiscript__tests__build_status_dialog.snap | 15 + ...nnot_lib__asciiscript__tests__buttons.snap | 7 + ...__asciiscript__tests__checkbox_states.snap | 6 + ...t_lib__asciiscript__tests__code_block.snap | 7 + ..._lib__asciiscript__tests__code_in_box.snap | 10 + ...ciiscript__tests__complex_nested_rows.snap | 11 + ...ciiscript__tests__confirmation_dialog.snap | 13 + ...ot_lib__asciiscript__tests__dashboard.snap | 25 + ...cript__tests__data_table_with_actions.snap | 17 + ...ciiscript__tests__database_query_tool.snap | 25 + ...ciiscript__tests__deeply_nested_boxes.snap | 21 + ...lib__asciiscript__tests__empty_layout.snap | 5 + ...ot_lib__asciiscript__tests__empty_row.snap | 5 + ...ib__asciiscript__tests__empty_section.snap | 5 + ...lib__asciiscript__tests__empty_window.snap | 8 + ...ipt__tests__error_dialog_with_details.snap | 17 + ...lib__asciiscript__tests__file_browser.snap | 15 + ...asciiscript__tests__git_commit_dialog.snap | 20 + ...script__tests__grid_dashboard_complex.snap | 26 + ...sciiscript__tests__grid_masonry_3_row.snap | 23 + ...__asciiscript__tests__grid_simple_2x2.snap | 16 + ...b__asciiscript__tests__input_variants.snap | 6 + ...t_lib__asciiscript__tests__list_basic.snap | 7 + ...ciiscript__tests__list_with_selection.snap | 7 + ...t_lib__asciiscript__tests__login_form.snap | 12 + ...ot_lib__asciiscript__tests__long_list.snap | 16 + ...ciiscript__tests__many_buttons_in_row.snap | 5 + ...__asciiscript__tests__many_checkboxes.snap | 18 + ...ot_lib__asciiscript__tests__many_rows.snap | 18 + ...ib__asciiscript__tests__minimal_input.snap | 5 + ...ib__asciiscript__tests__minimal_table.snap | 9 + ...sciiscript__tests__mixed_controls_row.snap | 9 + ...b__asciiscript__tests__multiline_code.snap | 10 + ...cript__tests__multiple_spacers_in_row.snap | 9 + ...asciiscript__tests__nested_containers.snap | 13 + ...__asciiscript__tests__nested_sections.snap | 10 + ...lib__asciiscript__tests__only_spacers.snap | 9 + ...__asciiscript__tests__package_manager.snap | 19 + ...ib__asciiscript__tests__progress_bars.snap | 9 + ...lib__asciiscript__tests__radio_states.snap | 7 + ...ib__asciiscript__tests__raw_ascii_art.snap | 7 + ...asciiscript__tests__registration_form.snap | 21 + ...sciiscript__tests__row_buttons_spaced.snap | 9 + ...b__asciiscript__tests__row_custom_gap.snap | 5 + ...t_lib__asciiscript__tests__row_layout.snap | 5 + ...t_lib__asciiscript__tests__row_no_gap.snap | 5 + ...__asciiscript__tests__row_with_spacer.snap | 9 + ..._asciiscript__tests__sample_dashboard.snap | 18 + ...iiscript__tests__sample_export_dialog.snap | 18 + ...asciiscript__tests__sample_login_form.snap | 13 + ...b__asciiscript__tests__search_filters.snap | 17 + ...iiscript__tests__section_with_content.snap | 7 + ...__asciiscript__tests__select_dropdown.snap | 6 + ...ot_lib__asciiscript__tests__separator.snap | 11 + ...b__asciiscript__tests__settings_panel.snap | 17 + ..._asciiscript__tests__single_item_list.snap | 5 + ...ib__asciiscript__tests__spacer_at_end.snap | 9 + ...__asciiscript__tests__spacer_at_start.snap | 9 + ...cript__tests__special_chars_in_labels.snap | 7 + ...b__asciiscript__tests__stacked_alerts.snap | 13 + ...iscript__tests__table_aligned_columns.snap | 10 + ..._lib__asciiscript__tests__table_basic.snap | 11 + ...t_lib__asciiscript__tests__tall_table.snap | 18 + ...lib__asciiscript__tests__text_aligned.snap | 11 + ..._lib__asciiscript__tests__text_simple.snap | 5 + ...sciiscript__tests__text_with_newlines.snap | 7 + ...script__tests__truncated_select_value.snap | 5 + ...iscript__tests__unicode_box_alignment.snap | 24 + ...__asciiscript__tests__unicode_in_text.snap | 5 + ...script__tests__very_long_button_label.snap | 5 + ...b__asciiscript__tests__very_long_text.snap | 9 + ...t_lib__asciiscript__tests__wide_table.snap | 11 + ...iscript__tests__window_explicit_width.snap | 9 + ...iiscript__tests__window_large_padding.snap | 13 + ...asciiscript__tests__window_no_padding.snap | 7 + ...ib__asciiscript__tests__window_titled.snap | 9 + ...ib__asciiscript__tests__wizard_dialog.snap | 17 + src-tauri/src/asciiscript/tests.rs | 1139 +++++++++++++ src-tauri/src/lib.rs | 1 + src-tauri/src/state.rs | 143 +- test-fixtures/sample.md | 93 + 93 files changed, 6065 insertions(+), 8 deletions(-) create mode 100644 src-tauri/src/asciiscript/ast.rs create mode 100644 src-tauri/src/asciiscript/lexer.rs create mode 100644 src-tauri/src/asciiscript/mod.rs create mode 100644 src-tauri/src/asciiscript/parser.rs create mode 100644 src-tauri/src/asciiscript/render.rs create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__alert_error.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__alert_info.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__alert_warning.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__alert_with_code.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__alert_with_multiple_lines.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__box_titled.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__build_status_dialog.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__buttons.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__checkbox_states.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__code_block.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__code_in_box.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__complex_nested_rows.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__confirmation_dialog.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__dashboard.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__data_table_with_actions.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__database_query_tool.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__deeply_nested_boxes.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__empty_layout.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__empty_row.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__empty_section.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__empty_window.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__error_dialog_with_details.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__file_browser.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__git_commit_dialog.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__grid_dashboard_complex.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__grid_masonry_3_row.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__grid_simple_2x2.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__input_variants.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__list_basic.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__list_with_selection.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__login_form.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__long_list.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__many_buttons_in_row.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__many_checkboxes.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__many_rows.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__minimal_input.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__minimal_table.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__mixed_controls_row.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__multiline_code.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__multiple_spacers_in_row.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__nested_containers.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__nested_sections.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__only_spacers.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__package_manager.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__progress_bars.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__radio_states.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__raw_ascii_art.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__registration_form.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__row_buttons_spaced.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__row_custom_gap.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__row_layout.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__row_no_gap.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__row_with_spacer.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__sample_dashboard.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__sample_export_dialog.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__sample_login_form.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__search_filters.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__section_with_content.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__select_dropdown.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__separator.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__settings_panel.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__single_item_list.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__spacer_at_end.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__spacer_at_start.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__special_chars_in_labels.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__stacked_alerts.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__table_aligned_columns.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__table_basic.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__tall_table.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__text_aligned.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__text_simple.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__text_with_newlines.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__truncated_select_value.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__unicode_box_alignment.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__unicode_in_text.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__very_long_button_label.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__very_long_text.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__wide_table.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__window_explicit_width.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__window_large_padding.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__window_no_padding.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__window_titled.snap create mode 100644 src-tauri/src/asciiscript/snapshots/annot_lib__asciiscript__tests__wizard_dialog.snap create mode 100644 src-tauri/src/asciiscript/tests.rs diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 342c640..519f76a 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -52,6 +52,6 @@ sublime_fuzzy = "0.7" similar = { version = "2", features = ["inline"] } [dev-dependencies] -insta = "1.45" +insta = "1.45.1" tempfile = "3.23.0" diff --git a/src-tauri/src/asciiscript/ast.rs b/src-tauri/src/asciiscript/ast.rs new file mode 100644 index 0000000..4b20d01 --- /dev/null +++ b/src-tauri/src/asciiscript/ast.rs @@ -0,0 +1,297 @@ +//! AST types for asciiscript DSL. +//! +//! The AST closely mirrors the grammar defined in docs/asciiscript-spec.md. + +use std::fmt; + +/// A complete asciiscript program. +#[derive(Debug, Clone, PartialEq)] +pub struct Program { + pub layout: Layout, +} + +/// The root layout container. +#[derive(Debug, Clone, PartialEq)] +pub struct Layout { + pub statements: Vec, + pub span: Span, +} + +/// A statement in a block - either a container or primitive. +#[derive(Debug, Clone, PartialEq)] +pub enum Statement { + Container(Container), + Primitive(Primitive), +} + +/// Container types that hold other statements. +#[derive(Debug, Clone, PartialEq)] +pub struct Container { + pub kind: ContainerKind, + pub title: Option, + pub modifiers: Modifiers, + pub statements: Vec, + pub span: Span, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ContainerKind { + Window, + Box, + Section, + Row, + Column, +} + +impl fmt::Display for ContainerKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ContainerKind::Window => write!(f, "window"), + ContainerKind::Box => write!(f, "box"), + ContainerKind::Section => write!(f, "section"), + ContainerKind::Row => write!(f, "row"), + ContainerKind::Column => write!(f, "column"), + } + } +} + +/// Primitive elements (leaf nodes). +#[derive(Debug, Clone, PartialEq)] +pub enum Primitive { + Text { + content: String, + modifiers: Modifiers, + span: Span, + }, + Input { + modifiers: Modifiers, + span: Span, + }, + Checkbox { + label: String, + checked: bool, + span: Span, + }, + Radio { + label: String, + selected: bool, + span: Span, + }, + Select { + value: String, + modifiers: Modifiers, + span: Span, + }, + Button { + label: String, + modifiers: Modifiers, + span: Span, + }, + Link { + text: String, + span: Span, + }, + Code { + content: String, + span: Span, + }, + Raw { + content: String, + span: Span, + }, + Separator { + span: Span, + }, + Spacer { + span: Span, + }, + Progress { + value: u8, // 0-100 + span: Span, + }, + Alert { + alert_type: AlertType, + statements: Vec, + span: Span, + }, + Table(Table), + List(List), +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum AlertType { + Error, + Warn, + Info, +} + +impl fmt::Display for AlertType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + AlertType::Error => write!(f, "error"), + AlertType::Warn => write!(f, "warn"), + AlertType::Info => write!(f, "info"), + } + } +} + +/// Table structure with header and rows. +#[derive(Debug, Clone, PartialEq)] +pub struct Table { + pub header: Option, + pub rows: Vec, + pub modifiers: Modifiers, + pub span: Span, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct TableHeader { + pub columns: Vec, + pub span: Span, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct TableColumn { + pub label: String, + pub modifiers: Modifiers, + pub span: Span, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct TableRow { + pub cells: Vec, + pub span: Span, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct TableCell { + pub content: String, + pub modifiers: Modifiers, + pub span: Span, +} + +/// List with selectable items. +#[derive(Debug, Clone, PartialEq)] +pub struct List { + pub items: Vec, + pub span: Span, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct ListItem { + pub content: String, + pub selected: bool, + pub span: Span, +} + +/// Modifiers (attributes + flags). +#[derive(Debug, Clone, PartialEq, Default)] +pub struct Modifiers { + pub width: Option, + pub height: Option, + pub padding: Option, + pub gap: Option, + pub align: Option, + pub style: Option