Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@

* Add `ft.use_dialog()` hook for declarative dialog management from within `@ft.component` functions, with frozen-diff reactive updates and automatic open/close lifecycle ([#6335](https://github.com/flet-dev/flet/pull/6335)) by @FeodorFitsner.
* Add `scrollable`, `pin_leading_to_top`, and `pin_trailing_to_bottom` properties to `NavigationRail` for scrollable content with optional pinned leading/trailing controls ([#1923](https://github.com/flet-dev/flet/issues/1923), [#6356](https://github.com/flet-dev/flet/pull/6356)) by @ndonkoHenri.
* Add `issues` property to `CodeEditor` (along with `Issue` and `IssueType` types) for displaying code analysis error markers in the gutter, with analysis performed on the Python side ([#6407](https://github.com/flet-dev/flet/pull/6407)) by @FeodorFitsner.

### Improvements

### Bug fixes

* Fix `flet build` and `flet publish` dependency parsing for `project.dependencies` and Poetry constraints with `<`/`<=`, and add coverage for normalized requirement handling ([#6332](https://github.com/flet-dev/flet/issues/6332), [#6340](https://github.com/flet-dev/flet/pull/6340)) by @td3447.
* Fix `CodeEditor` background not filling the entire area when `expand=True` ([#6407](https://github.com/flet-dev/flet/pull/6407)) by @FeodorFitsner.

### Other changes

Expand Down
28 changes: 17 additions & 11 deletions sdk/python/examples/controls/code_editor/example_2/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def main(page: ft.Page):
),
show_line_numbers=True,
show_folding_handles=True,
width=80,
width=60,
)

def handle_selection_change(e: ft.TextSelectionChangeEvent[fce.CodeEditor]):
Expand All @@ -91,12 +91,14 @@ async def move_caret_to_start(e: ft.Event[ft.Button]):
await editor.focus()
editor.selection = ft.TextSelection(base_offset=0, extent_offset=0)

page.padding = 0
page.spacing = 0
page.add(
ft.SafeArea(
expand=True,
content=ft.Column(
expand=True,
spacing=10,
expand=True,
controls=[
editor := fce.CodeEditor(
language=fce.CodeLanguage.PYTHON,
Expand All @@ -116,16 +118,20 @@ async def move_caret_to_start(e: ft.Event[ft.Button]):
on_selection_change=handle_selection_change,
expand=True,
),
selection := ft.Text("Select some text from the editor."),
selection_details := ft.Text(),
caret := ft.Text("Caret position: -"),
ft.Row(
spacing=10,
ft.Column(
margin=10,
controls=[
ft.Button("Select all text", on_click=select_all),
ft.Button(
"Move caret to start",
on_click=move_caret_to_start,
selection := ft.Text("Select some text from the editor."),
selection_details := ft.Text(),
caret := ft.Text("Caret position: -"),
ft.Row(
controls=[
ft.Button("Select all text", on_click=select_all),
ft.Button(
"Move caret to start",
on_click=move_caret_to_start,
),
],
),
],
),
Expand Down
65 changes: 65 additions & 0 deletions sdk/python/examples/controls/code_editor/example_4/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import asyncio
import json

import flet_code_editor as fce

import flet as ft

INVALID_JSON = """{
"name": "flet"
"version": 1
}"""


async def main(page: ft.Page):
page.title = "CodeEditor JSON analyzer"

debounce_task = None

def analyze_json(code):
issues = []
try:
json.loads(code)
except json.JSONDecodeError as ex:
issues.append(
fce.Issue(
line=ex.lineno - 1,
message=ex.msg,
type=fce.IssueType.ERROR,
)
)
editor.issues = issues
editor.update()

async def debounced_analyze(code):
await asyncio.sleep(0.5)
analyze_json(code)

def on_code_change(e):
nonlocal debounce_task
if debounce_task:
debounce_task.cancel()
debounce_task = asyncio.ensure_future(debounced_analyze(e.data))

editor = fce.CodeEditor(
language=fce.CodeLanguage.JSON,
code_theme=fce.CodeTheme.ATOM_ONE_LIGHT,
value=INVALID_JSON,
on_change=on_code_change,
gutter_style=fce.GutterStyle(
show_errors=True,
show_line_numbers=True,
show_folding_handles=True,
width=80,
),
expand=True,
)

page.add(ft.SafeArea(expand=True, content=editor))

# Run initial analysis
analyze_json(INVALID_JSON)


if __name__ == "__main__":
ft.run(main)
26 changes: 26 additions & 0 deletions sdk/python/examples/controls/code_editor/example_4/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[project]
name = "code-editor-example-4"
version = "1.0.0"
description = "CodeEditor with Python-side JSON analysis and gutter error markers."
requires-python = ">=3.10"
keywords = ["code editor", "json", "analyzer", "error markers", "gutter"]
authors = [{ name = "Flet team", email = "hello@flet.dev" }]
dependencies = ["flet", "flet-code-editor"]

[dependency-groups]
dev = ["flet-cli", "flet-desktop", "flet-web"]

[tool.flet.gallery]
categories = ["Utilities/CodeEditor"]

[tool.flet.metadata]
title = "JSON analyzer"
controls = ["SafeArea", "CodeEditor"]
layout_pattern = "single-panel"
complexity = "intermediate"
features = ["json validation", "error markers", "debounced analysis"]

[tool.flet]
org = "dev.flet"
company = "Flet"
copyright = "Copyright (C) 2023-2026 by Flet"
68 changes: 68 additions & 0 deletions sdk/python/examples/controls/code_editor/example_5/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import ast
import asyncio

import flet_code_editor as fce

import flet as ft

INVALID_PYTHON = """import os

def greet(name)
print(f"Hello, {name}!")

greet("World")
"""


async def main(page: ft.Page):
page.title = "CodeEditor Python analyzer"

debounce_task = None

def analyze_python(code):
issues = []
try:
ast.parse(code)
except SyntaxError as ex:
issues.append(
fce.Issue(
line=(ex.lineno or 1) - 1,
message=ex.msg,
type=fce.IssueType.ERROR,
)
)
editor.issues = issues
editor.update()

async def debounced_analyze(code):
await asyncio.sleep(0.5)
analyze_python(code)

def on_code_change(e):
nonlocal debounce_task
if debounce_task:
debounce_task.cancel()
debounce_task = asyncio.ensure_future(debounced_analyze(e.data))

editor = fce.CodeEditor(
language=fce.CodeLanguage.PYTHON,
code_theme=fce.CodeTheme.ATOM_ONE_LIGHT,
value=INVALID_PYTHON,
on_change=on_code_change,
gutter_style=fce.GutterStyle(
show_errors=True,
show_line_numbers=True,
show_folding_handles=True,
width=80,
),
expand=True,
)

page.add(ft.SafeArea(expand=True, content=editor))

# Run initial analysis
analyze_python(INVALID_PYTHON)


if __name__ == "__main__":
ft.run(main)
26 changes: 26 additions & 0 deletions sdk/python/examples/controls/code_editor/example_5/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[project]
name = "code-editor-example-5"
version = "1.0.0"
description = "CodeEditor with Python-side syntax analysis and gutter error markers."
requires-python = ">=3.10"
keywords = ["code editor", "python", "analyzer", "error markers", "gutter"]
authors = [{ name = "Flet team", email = "hello@flet.dev" }]
dependencies = ["flet", "flet-code-editor"]

[dependency-groups]
dev = ["flet-cli", "flet-desktop", "flet-web"]

[tool.flet.gallery]
categories = ["Utilities/CodeEditor"]

[tool.flet.metadata]
title = "Python analyzer"
controls = ["SafeArea", "CodeEditor"]
layout_pattern = "single-panel"
complexity = "intermediate"
features = ["python validation", "error markers", "debounced analysis"]

[tool.flet]
org = "dev.flet"
company = "Flet"
copyright = "Copyright (C) 2023-2026 by Flet"
10 changes: 10 additions & 0 deletions sdk/python/packages/flet-code-editor/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## 0.2.0

### Added

- `issues` property on `CodeEditor` for displaying code analysis error markers in the gutter, along with new `Issue` and `IssueType` types. Analysis is performed on the Python side via `on_change` and pushed to the editor.

### Fixed

- `CodeEditor` background not filling the entire area when `expand=True`.

## 0.1.0

Initial release.
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
from flet_code_editor.code_editor import CodeEditor
from flet_code_editor.types import CodeLanguage, CodeTheme, CustomCodeTheme, GutterStyle
from flet_code_editor.types import (
CodeLanguage,
CodeTheme,
CustomCodeTheme,
GutterStyle,
Issue,
IssueType,
)

__all__ = [
"CodeEditor",
"CodeLanguage",
"CodeTheme",
"CustomCodeTheme",
"GutterStyle",
"Issue",
"IssueType",
]
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
from dataclasses import field
from typing import Optional, Union

import flet as ft
from flet_code_editor.types import CodeLanguage, CodeTheme, CustomCodeTheme, GutterStyle
from flet_code_editor.types import (
CodeLanguage,
CodeTheme,
CustomCodeTheme,
GutterStyle,
Issue,
)

__all__ = ["CodeEditor"]

Expand Down Expand Up @@ -46,6 +53,9 @@ class CodeEditor(ft.LayoutControl):
autocomplete_words: Optional[list[str]] = None
"""Words offered by autocomplete."""

issues: list[Issue] = field(default_factory=list)
"""List of code analysis issues to display in the editor gutter."""

read_only: Optional[bool] = False
"""Whether the editor is read-only."""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@
import flet as ft
from flet.controls.core.markdown import MarkdownCodeTheme, MarkdownCustomCodeTheme

__all__ = ["CodeLanguage", "CodeTheme", "CustomCodeTheme", "GutterStyle"]
__all__ = [
"CodeLanguage",
"CodeTheme",
"CustomCodeTheme",
"GutterStyle",
"Issue",
"IssueType",
]


class CodeLanguage(Enum):
Expand Down Expand Up @@ -846,3 +853,36 @@ class GutterStyle:

show_line_numbers: bool = True
"""Whether to show line numbers in the gutter."""


class IssueType(Enum):
"""Severity level of a code analysis issue."""

ERROR = "error"
"""Error severity."""

WARNING = "warning"
"""Warning severity."""

INFO = "info"
"""Informational severity."""


@ft.value
class Issue:
"""A code analysis issue displayed in the editor gutter."""

line: int = 0
"""0-indexed line number where the issue occurs."""

message: str = ""
"""Description of the issue."""

type: Optional[IssueType] = None
"""Severity level: error, warning, or info."""

suggestion: Optional[str] = None
"""Optional suggested fix."""

url: Optional[str] = None
"""Optional URL for more information."""
Loading
Loading