diff --git a/src/myfasthtml/controls/DataGrid.py b/src/myfasthtml/controls/DataGrid.py
index 57e23dd..10d3580 100644
--- a/src/myfasthtml/controls/DataGrid.py
+++ b/src/myfasthtml/controls/DataGrid.py
@@ -24,7 +24,10 @@ from myfasthtml.controls.helpers import mk, icons
from myfasthtml.core.commands import Command
from myfasthtml.core.constants import ColumnType, ROW_INDEX_ID, FooterAggregation, DATAGRID_PAGE_SIZE, FILTER_INPUT_CID
from myfasthtml.core.dbmanager import DbObject
+from myfasthtml.core.dsls import DslsManager
+from myfasthtml.core.formatting.dsl.completion.FormattingCompletionEngine import FormattingCompletionEngine
from myfasthtml.core.formatting.dsl.definition import FormattingDSL
+from myfasthtml.core.formatting.dsl.parser import DSLParser
from myfasthtml.core.formatting.engine import FormattingEngine
from myfasthtml.core.instances import MultipleInstance
from myfasthtml.core.optimized_ft import OptimizedDiv
@@ -97,6 +100,7 @@ class DatagridSettings(DbObject):
self.open_file_visible: bool = True
self.open_settings_visible: bool = True
self.text_size: str = "sm"
+ self.enable_formatting: bool = True
class Commands(BaseCommands):
@@ -206,12 +210,20 @@ class DataGrid(MultipleInstance):
self._columns_manager.bind_command("ToggleColumn", self.commands.on_column_changed())
self._columns_manager.bind_command("UpdateColumn", self.commands.on_column_changed())
- editor_conf = DslEditorConf()
- self._formatting_editor = DataGridFormattingEditor(self,
- conf=editor_conf,
- dsl=FormattingDSL(),
- save_state=self._settings.save_state,
- _id="-formatting_editor")
+ if self._settings.enable_formatting:
+ completion_engine = FormattingCompletionEngine(self._parent, self.get_table_name())
+ editor_conf = DslEditorConf(engine_id=completion_engine.get_id())
+ dsl = FormattingDSL()
+ self._formatting_editor = DataGridFormattingEditor(self,
+ conf=editor_conf,
+ dsl=dsl,
+ save_state=self._settings.save_state,
+ _id="-formatting_editor")
+ # register the auto-completion for the formatter DSL
+ DslsManager.register(completion_engine,
+ DSLParser())
+ else:
+ self._formatting_editor = None
# other definitions
self._mouse_support = {
@@ -220,7 +232,7 @@ class DataGrid(MultipleInstance):
"shift+click": {"command": self.commands.on_click(), "hx_vals": "js:getCellId()"},
}
- logger.debug(f"DataGrid '{self._get_full_name()}' with id='{self._id}' created.")
+ logger.debug(f"DataGrid '{self.get_table_name()}' with id='{self._id}' created.")
@property
def _df(self):
@@ -298,9 +310,6 @@ class DataGrid(MultipleInstance):
self._state.selection.selected = pos
self._state.save()
- def _get_full_name(self):
- return f"{self._settings.namespace}.{self._settings.name}" if self._settings.namespace else self._settings.name
-
def init_from_dataframe(self, df, init_state=True):
def _get_column_type(dtype):
@@ -497,6 +506,9 @@ class DataGrid(MultipleInstance):
def get_settings(self):
return self._settings
+ def get_table_name(self):
+ return f"{self._settings.namespace}.{self._settings.name}" if self._settings.namespace else self._settings.name
+
def mk_headers(self):
resize_cmd = self.commands.set_column_width()
move_cmd = self.commands.move_column()
diff --git a/src/myfasthtml/controls/DataGridsManager.py b/src/myfasthtml/controls/DataGridsManager.py
index 32ad2d9..3320366 100644
--- a/src/myfasthtml/controls/DataGridsManager.py
+++ b/src/myfasthtml/controls/DataGridsManager.py
@@ -14,11 +14,7 @@ from myfasthtml.controls.helpers import mk
from myfasthtml.core.DataGridsRegistry import DataGridsRegistry
from myfasthtml.core.commands import Command
from myfasthtml.core.dbmanager import DbObject
-from myfasthtml.core.dsls import DslsManager
-from myfasthtml.core.formatting.dsl.completion.engine import FormattingCompletionEngine
from myfasthtml.core.formatting.dsl.completion.provider import DatagridMetadataProvider
-from myfasthtml.core.formatting.dsl.definition import FormattingDSL
-from myfasthtml.core.formatting.dsl.parser import DSLParser
from myfasthtml.core.formatting.presets import DEFAULT_STYLE_PRESETS, DEFAULT_FORMATTER_PRESETS
from myfasthtml.core.instances import InstancesManager, SingleInstance
from myfasthtml.icons.fluent_p1 import table_add20_regular
@@ -94,11 +90,6 @@ class DataGridsManager(SingleInstance, DatagridMetadataProvider):
# Global presets shared across all DataGrids
self.style_presets: dict = DEFAULT_STYLE_PRESETS.copy()
self.formatter_presets: dict = DEFAULT_FORMATTER_PRESETS.copy()
-
- # register the auto-completion for the formatter DSL
- DslsManager.register(FormattingDSL().get_id(),
- FormattingCompletionEngine(self),
- DSLParser())
def upload_from_source(self):
file_upload = FileUpload(self)
@@ -112,7 +103,7 @@ class DataGridsManager(SingleInstance, DatagridMetadataProvider):
namespace = file_upload.get_file_basename()
name = file_upload.get_sheet_name()
dg_conf = DatagridConf(namespace=namespace, name=name)
- dg = DataGrid(self._tabs_manager, conf=dg_conf, save_state=True) # first time the Datagrid is created
+ dg = DataGrid(self, conf=dg_conf, save_state=True) # first time the Datagrid is created
dg.init_from_dataframe(df)
self._registry.put(namespace, name, dg.get_id())
document = DocumentDefinition(
@@ -133,7 +124,7 @@ class DataGridsManager(SingleInstance, DatagridMetadataProvider):
document_id = self._tree.get_bag(node_id)
try:
document = next(filter(lambda x: x.document_id == document_id, self._state.elements))
- dg = DataGrid(self._tabs_manager, _id=document.datagrid_id) # reload the state & settings
+ dg = DataGrid(self, _id=document.datagrid_id) # reload the state & settings
return self._tabs_manager.show_or_create_tab(document.tab_id, document.name, dg)
except StopIteration:
# the selected node is not a document (it's a folder)
@@ -157,7 +148,7 @@ class DataGridsManager(SingleInstance, DatagridMetadataProvider):
raise ValueError(f"No document found for tab {tab_id}")
# Recreate the DataGrid with its saved state
- dg = DataGrid(self._tabs_manager, _id=document.datagrid_id) # reload the state & settings
+ dg = DataGrid(self, _id=document.datagrid_id) # reload the state & settings
return dg
def clear_tree(self):
diff --git a/src/myfasthtml/controls/DslEditor.py b/src/myfasthtml/controls/DslEditor.py
index e0ba9e0..eca8c70 100644
--- a/src/myfasthtml/controls/DslEditor.py
+++ b/src/myfasthtml/controls/DslEditor.py
@@ -32,6 +32,7 @@ class DslEditorConf:
linting: bool = True
placeholder: str = ""
readonly: bool = False
+ engine_id: str = None # id of the DSL engine to use for autocompletion
class DslEditorState(DbObject):
@@ -141,7 +142,7 @@ class DslEditor(MultipleInstance):
simple_mode_config = None
if hasattr(self._dsl, 'simple_mode_config'):
simple_mode_config = self._dsl.simple_mode_config
-
+
config = {
"elementId": str(self._id),
"textareaId": f"ta_{self._id}",
@@ -151,7 +152,7 @@ class DslEditor(MultipleInstance):
"placeholder": self.conf.placeholder,
"readonly": self.conf.readonly,
"updateCommandId": str(self.commands.update_content().id),
- "dslId": self._dsl.get_id(),
+ "dslId": self.conf.engine_id,
"dsl": {
"name": self._dsl.name,
"completions": self._dsl.completions,
diff --git a/src/myfasthtml/core/dsl/base_completion.py b/src/myfasthtml/core/dsl/base_completion.py
index 3c87d1f..94e3f99 100644
--- a/src/myfasthtml/core/dsl/base_completion.py
+++ b/src/myfasthtml/core/dsl/base_completion.py
@@ -33,6 +33,7 @@ class BaseCompletionEngine(ABC):
provider: Metadata provider for context-aware suggestions
"""
self.provider = provider
+ self._id = type(self).__name__
def get_completions(self, text: str, cursor: Position) -> CompletionResult:
"""
@@ -169,4 +170,4 @@ class BaseCompletionEngine(ABC):
)
def get_id(self):
- return type(self).__name__
+ return self._id
diff --git a/src/myfasthtml/core/dsl/base_provider.py b/src/myfasthtml/core/dsl/base_provider.py
index 4b2992a..58371dc 100644
--- a/src/myfasthtml/core/dsl/base_provider.py
+++ b/src/myfasthtml/core/dsl/base_provider.py
@@ -19,7 +19,7 @@ class BaseMetadataProvider(Protocol):
can extend this with additional methods.
"""
- def get_style_presets(self) -> list[str]:
+ def list_style_presets(self) -> list[str]:
"""
Return the list of available style preset names.
@@ -28,7 +28,7 @@ class BaseMetadataProvider(Protocol):
"""
...
- def get_format_presets(self) -> list[str]:
+ def list_format_presets(self) -> list[str]:
"""
Return the list of available format preset names.
diff --git a/src/myfasthtml/core/dsls.py b/src/myfasthtml/core/dsls.py
index 25276db..c6b7069 100644
--- a/src/myfasthtml/core/dsls.py
+++ b/src/myfasthtml/core/dsls.py
@@ -14,9 +14,9 @@ class DslsManager:
dsls: dict[str, DslDefinition] = {}
@staticmethod
- def register(dsl_id: str, completion: BaseCompletionEngine, validation: DSLParser):
+ def register(completion: BaseCompletionEngine, validation: DSLParser):
# then engine_id is actually the DSL id
- DslsManager.dsls[dsl_id] = DslDefinition(completion, validation)
+ DslsManager.dsls[completion.get_id()] = DslDefinition(completion, validation)
@staticmethod
def get_completion_engine(engine_id) -> BaseCompletionEngine:
diff --git a/src/myfasthtml/core/formatting/dsl/completion/engine.py b/src/myfasthtml/core/formatting/dsl/completion/FormattingCompletionEngine.py
similarity index 92%
rename from src/myfasthtml/core/formatting/dsl/completion/engine.py
rename to src/myfasthtml/core/formatting/dsl/completion/FormattingCompletionEngine.py
index 650cdb8..d73bf80 100644
--- a/src/myfasthtml/core/formatting/dsl/completion/engine.py
+++ b/src/myfasthtml/core/formatting/dsl/completion/FormattingCompletionEngine.py
@@ -3,8 +3,10 @@ Completion engine for the formatting DSL.
Implements the BaseCompletionEngine for DataGrid formatting rules.
"""
+
from myfasthtml.core.dsl.base_completion import BaseCompletionEngine
from myfasthtml.core.dsl.types import Position, Suggestion, CompletionResult
+from myfasthtml.core.utils import make_safe_id
from . import suggestions as suggestions_module
from .contexts import Context, DetectedScope, detect_scope, detect_context
from .provider import DatagridMetadataProvider
@@ -21,7 +23,7 @@ class FormattingCompletionEngine(BaseCompletionEngine):
- Conditions with operators and values
"""
- def __init__(self, provider: DatagridMetadataProvider):
+ def __init__(self, provider: DatagridMetadataProvider, table_name: str):
"""
Initialize the completion engine.
@@ -30,6 +32,8 @@ class FormattingCompletionEngine(BaseCompletionEngine):
"""
super().__init__(provider)
self.provider: DatagridMetadataProvider = provider
+ self.table_name: str = table_name # current table name
+ self._id = "formatting_completion_engine#" + make_safe_id(table_name)
def detect_scope(self, text: str, current_line: int) -> DetectedScope:
"""
diff --git a/src/myfasthtml/core/formatting/dsl/completion/provider.py b/src/myfasthtml/core/formatting/dsl/completion/provider.py
index 627c7e6..a1592e3 100644
--- a/src/myfasthtml/core/formatting/dsl/completion/provider.py
+++ b/src/myfasthtml/core/formatting/dsl/completion/provider.py
@@ -5,10 +5,12 @@ Provides access to DataGrid metadata (columns, values, row counts)
for context-aware autocompletion.
"""
-from typing import Protocol, Any
+from typing import Any
+
+from myfasthtml.core.dsl.base_provider import BaseMetadataProvider
-class DatagridMetadataProvider(Protocol):
+class DatagridMetadataProvider(BaseMetadataProvider):
"""
Protocol for providing DataGrid metadata to the autocompletion engine.
@@ -70,25 +72,3 @@ class DatagridMetadataProvider(Protocol):
Number of rows
"""
...
-
- def list_style_presets(self) -> list[str]:
- """
- Return the list of available style preset names.
-
- Includes default presets (primary, error, etc.) and custom presets.
-
- Returns:
- List of style preset names
- """
- ...
-
- def list_format_presets(self) -> list[str]:
- """
- Return the list of available format preset names.
-
- Includes default presets (EUR, USD, etc.) and custom presets.
-
- Returns:
- List of format preset names
- """
- ...
diff --git a/src/myfasthtml/core/utils.py b/src/myfasthtml/core/utils.py
index 302e306..1f91021 100644
--- a/src/myfasthtml/core/utils.py
+++ b/src/myfasthtml/core/utils.py
@@ -375,7 +375,7 @@ def post(session, b_id: str, values: dict):
:param values:
:return:
"""
- logger.debug(f"Entering {Routes.Bindings} with {session=}, {b_id=}, {values=}")
+ logger.debug(f"Entering {Routes.Bindings} with session='{debug_session(session)}', {b_id=}, {values=}")
from myfasthtml.core.bindings import BindingsManager
binding = BindingsManager.get_binding(b_id)
if binding:
@@ -396,7 +396,8 @@ def get(session, e_id: str, text: str, line: int, ch: int):
:param ch:
:return:
"""
- logger.debug(f"Entering {Routes.Completions} with {session=}, {e_id=}, {text=}, {line=}, {ch}")
+ logger.debug(
+ f"Entering {Routes.Completions} with session='{debug_session(session)}', {e_id=}, text={len(text)} char(s), {line=}, {ch=}")
completion = DslsManager.get_completion_engine(e_id)
result = completion.get_completions(text, Position(line, ch))
return result.to_dict()
@@ -413,7 +414,8 @@ def get(session, e_id: str, text: str, line: int, ch: int):
:param ch:
:return:
"""
- logger.debug(f"Entering {Routes.Validations} with {session=}, {e_id=}, {text=}, {line=}, {ch}")
+ logger.debug(
+ f"Entering {Routes.Validations} with session='{debug_session(session)}', {e_id=}, text={len(text)} char(s), {line=}, {ch=}")
validation = DslsManager.get_validation_parser(e_id)
try:
validation.parse(text)
diff --git a/tests/core/formatting/dsl/test_completion.py b/tests/core/formatting/dsl/test_completion.py
index b57c41a..974d40a 100644
--- a/tests/core/formatting/dsl/test_completion.py
+++ b/tests/core/formatting/dsl/test_completion.py
@@ -15,7 +15,7 @@ from myfasthtml.core.formatting.dsl.completion.contexts import (
detect_context,
)
from myfasthtml.core.formatting.dsl.completion.suggestions import get_suggestions
-from myfasthtml.core.formatting.dsl.completion.engine import (
+from myfasthtml.core.formatting.dsl.completion.FormattingCompletionEngine import (
FormattingCompletionEngine,
get_completions,
)