I can validate formatting in editor

This commit is contained in:
2026-02-01 21:49:46 +01:00
parent d7ec99c3d9
commit 0620cb678b
23 changed files with 794 additions and 501 deletions

View File

@@ -1,7 +1,7 @@
from myfasthtml.core.dbmanager import DbManager
from myfasthtml.core.instances import SingleInstance
DATAGRIDS_REGISTRY_ENTRY_KEY = "DataGridsRegistryEntry"
DATAGRIDS_REGISTRY_ENTRY_KEY = "data_grids_registry"
class DataGridsRegistry(SingleInstance):

View File

@@ -1,14 +0,0 @@
class CompletionsManager:
completions = {}
@staticmethod
def register(engine):
CompletionsManager.completions[engine.get_id()] = engine
@staticmethod
def get_completions(engine_id):
return CompletionsManager.completions[engine_id]
@staticmethod
def reset():
CompletionsManager.completions = {}

View File

@@ -15,6 +15,7 @@ class Routes:
Commands = "/commands"
Bindings = "/bindings"
Completions = "/completions"
Validations = "/validations"
class ColumnType(Enum):

View File

@@ -43,7 +43,9 @@ class DbObject:
def __init__(self, owner: BaseInstance, name=None, db_manager=None, save_state=True):
self._owner = owner
self._name = name or owner.get_full_id()
self._name = name or owner.get_id()
if self._name.startswith(("#", "-")) and owner.get_parent() is not None:
self._name = owner.get_parent().get_id() + self._name
self._db_manager = db_manager or DbManager(self._owner)
self._save_state = save_state

View File

@@ -13,6 +13,7 @@ from myfasthtml.core.dsl.lark_to_lezer import (
lark_to_lezer_grammar,
extract_completions_from_grammar,
)
from myfasthtml.core.utils import make_safe_id
class DSLDefinition(ABC):
@@ -82,3 +83,6 @@ class DSLDefinition(ABC):
"lezerGrammar": self.lezer_grammar,
"completions": self.completions,
}
def get_id(self):
return make_safe_id(self.name)

View File

@@ -0,0 +1,31 @@
from dataclasses import dataclass
from myfasthtml.core.dsl.base_completion import BaseCompletionEngine
from myfasthtml.core.formatting.dsl.parser import DSLParser
@dataclass
class DslDefinition:
completion: BaseCompletionEngine
validation: DSLParser # To do, this parser is not generic (specific to the Formatting DSL)
class DslsManager:
dsls: dict[str, DslDefinition] = {}
@staticmethod
def register(dsl_id: str, completion: BaseCompletionEngine, validation: DSLParser):
# then engine_id is actually the DSL id
DslsManager.dsls[dsl_id] = DslDefinition(completion, validation)
@staticmethod
def get_completion_engine(engine_id) -> BaseCompletionEngine:
return DslsManager.dsls[engine_id].completion
@staticmethod
def get_validation_parser(engine_id) -> DSLParser:
return DslsManager.dsls[engine_id].validation
@staticmethod
def reset():
DslsManager.dsls = {}

View File

@@ -22,7 +22,7 @@ class DatagridMetadataProvider(Protocol):
DataGrid names follow the pattern namespace.name (multi-level namespaces).
"""
def get_tables(self) -> list[str]:
def list_tables(self) -> list[str]:
"""
Return the list of available DataGrid names.
@@ -31,7 +31,7 @@ class DatagridMetadataProvider(Protocol):
"""
...
def get_columns(self, table_name: str) -> list[str]:
def list_columns(self, table_name: str) -> list[str]:
"""
Return the column names for a specific DataGrid.
@@ -43,7 +43,7 @@ class DatagridMetadataProvider(Protocol):
"""
...
def get_column_values(self, table_name, column_name: str) -> list[Any]:
def list_column_values(self, table_name, column_name: str) -> list[Any]:
"""
Return the distinct values for a column in the current DataGrid.
@@ -71,7 +71,7 @@ class DatagridMetadataProvider(Protocol):
"""
...
def get_style_presets(self) -> list[str]:
def list_style_presets(self) -> list[str]:
"""
Return the list of available style preset names.
@@ -82,7 +82,7 @@ class DatagridMetadataProvider(Protocol):
"""
...
def get_format_presets(self) -> list[str]:
def list_format_presets(self) -> list[str]:
"""
Return the list of available format preset names.

View File

@@ -160,9 +160,9 @@ def _get_column_suggestions(provider: DatagridMetadataProvider) -> list[Suggesti
"""Get column name suggestions from provider."""
try:
# Try to get columns from the first available table
tables = provider.get_tables()
tables = provider.list_tables()
if tables:
columns = provider.get_columns(tables[0])
columns = provider.list_columns(tables[0])
return [Suggestion(col, "Column", "column") for col in columns]
except Exception:
pass
@@ -174,9 +174,9 @@ def _get_column_suggestions_with_closing_quote(
) -> list[Suggestion]:
"""Get column name suggestions with closing quote."""
try:
tables = provider.get_tables()
tables = provider.list_tables()
if tables:
columns = provider.get_columns(tables[0])
columns = provider.list_columns(tables[0])
return [Suggestion(f'{col}"', "Column", "column") for col in columns]
except Exception:
pass
@@ -189,7 +189,7 @@ def _get_style_preset_suggestions(provider: DatagridMetadataProvider) -> list[Su
# Add provider presets if available
try:
custom_presets = provider.get_style_presets()
custom_presets = provider.list_style_presets()
for preset in custom_presets:
# Check if it's already in default presets
if not any(s.label == preset for s in presets.STYLE_PRESETS):
@@ -212,7 +212,7 @@ def _get_style_preset_suggestions_quoted(
# Add provider presets if available
try:
custom_presets = provider.get_style_presets()
custom_presets = provider.list_style_presets()
for preset in custom_presets:
if not any(s.label == preset for s in presets.STYLE_PRESETS):
suggestions.append(Suggestion(f'"{preset}"', "Custom preset", "preset"))
@@ -232,7 +232,7 @@ def _get_format_preset_suggestions(provider: DatagridMetadataProvider) -> list[S
# Add provider presets if available
try:
custom_presets = provider.get_format_presets()
custom_presets = provider.list_format_presets()
for preset in custom_presets:
if not any(s.label == preset for s in presets.FORMAT_PRESETS):
suggestions.append(Suggestion(preset, "Custom preset", "preset"))
@@ -251,7 +251,7 @@ def _get_row_index_suggestions(provider: DatagridMetadataProvider) -> list[Sugge
suggestions = []
try:
tables = provider.get_tables()
tables = provider.list_tables()
if tables:
row_count = provider.get_row_count(tables[0])
if row_count > 0:
@@ -285,7 +285,7 @@ def _get_column_value_suggestions(
return []
try:
values = provider.get_column_values(scope.column_name)
values = provider.list_column_values(scope.column_name)
suggestions = []
for value in values:
if value is None:

View File

@@ -116,7 +116,7 @@ class BaseInstance:
_id = f"{prefix}-{str(uuid.uuid4())}"
return _id
if _id.startswith("-") and parent is not None:
if _id.startswith(("-", "#")) and parent is not None:
return f"{parent.get_id()}{_id}"
return _id

View File

@@ -10,6 +10,9 @@ from rich.table import Table
from starlette.routing import Mount
from myfasthtml.core.constants import Routes, ROUTE_ROOT
from myfasthtml.core.dsl.types import Position
from myfasthtml.core.dsls import DslsManager
from myfasthtml.core.formatting.dsl import DSLSyntaxError
from myfasthtml.test.MyFT import MyFT
utils_app, utils_rt = fast_app()
@@ -383,12 +386,41 @@ def post(session, b_id: str, values: dict):
@utils_rt(Routes.Completions)
def get(session, c_id, text: str, line: int, ch: int):
def get(session, e_id: str, text: str, line: int, ch: int):
"""
Default routes for Domaine Specific Languages completion
:param session:
:param c_id:
:param values:
:param e_id: engine_id
:param text:
:param line:
:param ch:
:return:
"""
logger.debug(f"Entering {Routes.Bindings} with {session=}, {c_id=}, {values=}")
logger.debug(f"Entering {Routes.Completions} with {session=}, {e_id=}, {text=}, {line=}, {ch}")
completion = DslsManager.get_completion_engine(e_id)
result = completion.get_completions(text, Position(line, ch))
return result.to_dict()
@utils_rt(Routes.Validations)
def get(session, e_id: str, text: str, line: int, ch: int):
"""
Default routes for Domaine Specific Languages syntax validation
:param session:
:param e_id:
:param text:
:param line:
:param ch:
:return:
"""
logger.debug(f"Entering {Routes.Validations} with {session=}, {e_id=}, {text=}, {line=}, {ch}")
validation = DslsManager.get_validation_parser(e_id)
try:
validation.parse(text)
return {"errors": []}
except DSLSyntaxError as e:
return {"errors": [{
"line": e.line or 1,
"column": e.column or 1,
"message": e.message
}]}