Added "table" and "tables" in the DSL

This commit is contained in:
2026-02-07 22:48:51 +01:00
parent 08c8c00e28
commit 6160e91665
18 changed files with 717 additions and 54 deletions

View File

@@ -48,12 +48,14 @@ Rules are indented (Python-style) under their scope.
Scopes define which cells a rule applies to:
| Scope | Syntax | Applies To |
|-------|--------|------------|
| **Column** | `column <name>:` | All cells in the column |
| **Row** | `row <index>:` | All cells in the row |
| **Cell (coordinates)** | `cell (<col>, <row>):` | Single cell by position |
| **Cell (ID)** | `cell <cell_id>:` | Single cell by ID |
| Scope | Syntax | Applies To | Specificity |
|-------|--------|------------|-------------|
| **Cell (coordinates)** | `cell (<col>, <row>):` | Single cell by position | Highest (1) |
| **Cell (ID)** | `cell <cell_id>:` | Single cell by ID | Highest (1) |
| **Row** | `row <index>:` | All cells in the row | High (2) |
| **Column** | `column <name>:` | All cells in the column | Medium (3) |
| **Table** | `table "<name>":` | All cells in a specific table | Low (4) |
| **Tables** | `tables:` | All cells in all tables (global) | Lowest (5) |
**Column scope:**
@@ -97,6 +99,24 @@ cell tcell_grid1-3-2:
style(background_color="yellow")
```
**Table scope:**
```python
# Table by name (must match DataGrid _settings.name)
table "products":
style("neutral")
format.number(precision=2)
```
**Tables scope (global):**
```python
# All tables in the application
tables:
style(color="#333")
format.date(format="%Y-%m-%d")
```
### Rules
A rule consists of optional **style**, optional **format**, and optional **condition**:
@@ -355,10 +375,12 @@ program : scope+
// Scopes
scope : scope_header NEWLINE INDENT rule+ DEDENT
scope_header : column_scope | row_scope | cell_scope
scope_header : column_scope | row_scope | cell_scope | table_scope | tables_scope
column_scope : "column" column_name ":"
row_scope : "row" INTEGER ":"
cell_scope : "cell" cell_ref ":"
table_scope : "table" QUOTED_STRING ":"
tables_scope : "tables" ":"
column_name : NAME | QUOTED_STRING
cell_ref : "(" column_name "," INTEGER ")" | CELL_ID
@@ -452,6 +474,21 @@ row 0:
style("neutral", bold=True)
```
**Apply default style to all cells in a table:**
```python
table "products":
style("neutral")
format.number(precision=2)
```
**Apply global styles to all tables:**
```python
tables:
style(font_size="14px")
```
### Advanced Examples
**Compare with another column:**
@@ -496,9 +533,17 @@ column status:
format.enum(source={"draft": "Brouillon", "pending": "En attente", "approved": "Approuvé"}, default="Inconnu")
```
**Complete example - Financial report:**
**Complete example - Financial report with hierarchy:**
```python
# Global styling for all tables
tables:
style(font_size="14px", color="#333")
# Table-specific defaults
table "financial_report":
format.number(precision=2)
# Header styling
row 0:
style("neutral", bold=True)
@@ -533,6 +578,13 @@ cell (amount, 10):
style("accent", bold=True)
```
**Note on hierarchy:** In the example above, for the cell `(amount, 10)`, the styles are applied in this order:
1. Cell-specific rule wins (accent, bold)
2. If no cell rule, column rules apply (amount formatting + conditional styles)
3. If no column rule, row rules apply (header bold)
4. If no row rule, table rules apply (financial_report precision)
5. If no table rule, global rules apply (tables font size and color)
---
## Autocompletion
@@ -579,8 +631,9 @@ The DSL editor provides context-aware autocompletion to help users write rules e
| Context | Trigger | Suggestions |
|---------|---------|-------------|
| **Scope keyword** | Start of line | `column`, `row`, `cell` |
| **Scope keyword** | Start of line | `column`, `row`, `cell`, `table`, `tables` |
| **Column name** | After `column ` | Column names from DataGrid |
| **Table name** | After `table ` | Table name from current DataGrid (_settings.name) |
| **Style preset** | Inside `style("` | Style presets |
| **Style parameter** | Inside `style(... , ` | `bold`, `italic`, `color`, etc. |
| **Format preset** | Inside `format("` | Format presets |
@@ -609,6 +662,13 @@ column amount: │ (new line, indent)
style("error", bold=True) if │ value, col., row., not
style("error", bold=True) if value │ ==, !=, <, >, in, ...
style("error", bold=True) if value < │ [number input]
tab │ table, tables
table │ [table name from current grid]
table "products": │ (new line, indent)
tables │ tables
tables: │ (new line, indent)
```
---
@@ -1166,12 +1226,14 @@ class DatagridMetadataProvider(Protocol):
| Context | Trigger | Suggestions |
|---------|---------|-------------|
| `SCOPE_KEYWORD` | Start of non-indented line | `column`, `row`, `cell` |
| `SCOPE_KEYWORD` | Start of non-indented line | `column`, `row`, `cell`, `table`, `tables` |
| `COLUMN_NAME` | After `column ` | Column names from DataGrid |
| `ROW_INDEX` | After `row ` | First 10 indices + last index |
| `CELL_START` | After `cell ` | `(` |
| `CELL_COLUMN` | After `cell (` | Column names |
| `CELL_ROW` | After `cell (col, ` | First 10 indices + last index |
| `TABLE_NAME` | After `table ` | Table name from current DataGrid (_settings.name) |
| `TABLES_SCOPE` | After `tables` | `:` |
| `RULE_START` | Start of indented line (after scope) | `style(`, `format(`, `format.` |
| `STYLE_ARGS` | After `style(` (no quote) | Presets with quotes + named params (`bold=`, `color=`, ...) |
| `STYLE_PRESET` | Inside `style("` | Style presets |
@@ -1313,16 +1375,18 @@ The following features are excluded from autocompletion for simplicity:
| DSL Grammar (lark) | :white_check_mark: Implemented | `src/myfasthtml/core/formatting/dsl/grammar.py` |
| DSL Parser | :white_check_mark: Implemented | `src/myfasthtml/core/formatting/dsl/parser.py` |
| DSL Transformer | :white_check_mark: Implemented | `src/myfasthtml/core/formatting/dsl/transformer.py` |
| Scope Dataclasses | :white_check_mark: Implemented | `src/myfasthtml/core/formatting/dsl/scopes.py` |
| Scope Dataclasses (Column, Row, Cell) | :white_check_mark: Implemented | `src/myfasthtml/core/formatting/dsl/scopes.py` |
| Scope Dataclasses (Table, Tables) | :o: To implement | `src/myfasthtml/core/formatting/dsl/scopes.py` |
| Exceptions | :white_check_mark: Implemented | `src/myfasthtml/core/formatting/dsl/exceptions.py` |
| Public API (`parse_dsl()`) | :white_check_mark: Implemented | `src/myfasthtml/core/formatting/dsl/__init__.py` |
| Unit Tests (Parser) | :white_check_mark: ~35 tests | `tests/core/formatting/dsl/test_dsl_parser.py` |
| **Autocompletion** | | |
| DatagridMetadataProvider | :white_check_mark: Implemented | `src/myfasthtml/core/formatting/dsl/completion/provider.py` |
| Scope Detector | :white_check_mark: Implemented | `src/myfasthtml/core/formatting/dsl/completion/contexts.py` |
| Context Detector | :white_check_mark: Implemented | `src/myfasthtml/core/formatting/dsl/completion/contexts.py` |
| Suggestions Generator | :white_check_mark: Implemented | `src/myfasthtml/core/formatting/dsl/completion/suggestions.py` |
| Completion Engine | :white_check_mark: Implemented | `src/myfasthtml/core/formatting/dsl/completion/engine.py` |
| Scope Detector (Column, Row, Cell) | :white_check_mark: Implemented | `src/myfasthtml/core/formatting/dsl/completion/contexts.py` |
| Scope Detector (Table, Tables) | :o: To implement | `src/myfasthtml/core/formatting/dsl/completion/contexts.py` |
| Context Detector | :white_check_mark: Implemented | `FormattingCompletionEngine.py` |
| Suggestions Generator | :white_check_mark: Implemented | `FormattingCompletionEngine.py` |
| Completion Engine | :white_check_mark: Implemented | `FormattingCompletionEngine.py` |
| Presets | :white_check_mark: Implemented | `src/myfasthtml/core/formatting/dsl/completion/presets.py` |
| Unit Tests (Completion) | :white_check_mark: ~50 tests | `tests/core/formatting/dsl/test_completion.py` |
| REST Endpoint | :white_check_mark: Implemented | `src/myfasthtml/core/utils.py``/myfasthtml/completions` |