flet-code-editor-dsl 0.3.1__tar.gz → 0.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. {flet_code_editor_dsl-0.3.1/src/flet_code_editor_dsl.egg-info → flet_code_editor_dsl-0.3.2}/PKG-INFO +27 -24
  2. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/README.md +26 -23
  3. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/pyproject.toml +1 -1
  4. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/src/flet_code_editor_dsl/__init__.py +3 -1
  5. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/src/flet_code_editor_dsl/flet_code_editor_dsl.py +7 -0
  6. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2/src/flet_code_editor_dsl.egg-info}/PKG-INFO +27 -24
  7. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/src/flutter/flet_code_editor_dsl/lib/src/code_editor.dart +65 -0
  8. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/src/flutter/flet_code_editor_dsl/lib/src/tokenizer.dart +11 -2
  9. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/src/flutter/flet_code_editor_dsl/pubspec.yaml +1 -1
  10. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/LICENSE +0 -0
  11. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/MANIFEST.in +0 -0
  12. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/setup.cfg +0 -0
  13. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/src/flet_code_editor_dsl/language.py +0 -0
  14. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/src/flet_code_editor_dsl.egg-info/SOURCES.txt +0 -0
  15. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/src/flet_code_editor_dsl.egg-info/dependency_links.txt +0 -0
  16. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/src/flet_code_editor_dsl.egg-info/requires.txt +0 -0
  17. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/src/flet_code_editor_dsl.egg-info/top_level.txt +0 -0
  18. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/src/flutter/__init__.py +0 -0
  19. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/src/flutter/flet_code_editor_dsl/__init__.py +0 -0
  20. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/src/flutter/flet_code_editor_dsl/lib/flet_code_editor_dsl.dart +0 -0
  21. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/src/flutter/flet_code_editor_dsl/lib/src/extension.dart +0 -0
  22. {flet_code_editor_dsl-0.3.1 → flet_code_editor_dsl-0.3.2}/src/flutter/flet_code_editor_dsl/lib/src/regex_highlighter.dart +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flet-code-editor-dsl
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: Flet code editors with syntax highlighting: EditorTokens (tokenizer) and EditorRegex (regex)
5
5
  Author-email: obgwew <obgwew@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -25,7 +25,7 @@ Dynamic: license-file
25
25
  ## Table of Contents
26
26
 
27
27
  1. [Overview](#overview)
28
- 2. [What's New in 0.3.0 / Migration](#whats-new-in-030--migration)
28
+ 2. [What's New in 0.3.2 / Migration](#whats-new-in-032--migration)
29
29
  3. [Features](#features)
30
30
  4. [Requirements](#requirements)
31
31
  5. [Installation](#installation)
@@ -97,9 +97,9 @@ lang = ce.Language(
97
97
 
98
98
  and hand `lang.to_json()` to `EditorTokens`.
99
99
 
100
- ## What's New in 0.3.0 / Migration
100
+ ## What's New in 0.3.2 / Migration
101
101
 
102
- ### 0.3.0
102
+ ### 0.3.2
103
103
 
104
104
  | Change | Details |
105
105
  |--------|---------|
@@ -109,6 +109,8 @@ and hand `lang.to_json()` to `EditorTokens`.
109
109
  | **Touch support** | New selection menu at the caret/handles, optional toolbar and cursor pad, magnifier, `scroll_mode`. See [Mobile / Touch Features](#mobile--touch-features). |
110
110
  | **Paste fix** | Cut/copy/paste from the new menu/toolbar read the clipboard directly and normalize line endings and control characters before inserting. |
111
111
  | **New Dart files** | `regex_highlighter.dart` (regex engine). `code_editor.dart` is now shared by both controls. The old `src/flet_code_editor_dsl.dart` (`CodeField` widget) was deleted. |
112
+ | **Number literals** | `0b…` now accepts only `0`/`1` and `0o…` only `0`–`7` (before, they accepted any hex digit, so `0b1010f` was one number). `0x…` is unchanged. |
113
+ | **Sigils** | If the longest matching prefix has no name after it, shorter prefixes are tried next (for example `$$` and `$` defined together: a lone `$$ ` now falls back to `$`). |
112
114
 
113
115
  Rename in your code:
114
116
 
@@ -120,11 +122,11 @@ ce.FletCodeField(rules=[...]) ce.EditorRegex(rules=[...])
120
122
 
121
123
  Because the Dart side changed, **rebuild your app** after upgrading.
122
124
 
123
- ### 0.2.0 (from the original `CodeEditor` API)
125
+ ### Migrating from the original `CodeEditor` API
124
126
 
125
127
  The earlier regex-based `CodeEditor` control and its `rule()` / `group()` / `pair()` helpers no longer exist.
126
128
 
127
- | Original API | 0.2.0+ |
129
+ | Original API | 0.3.2 |
128
130
  |-------|-------|
129
131
  | Control `CodeEditor` | `EditorTokens` (tokenizer) and `EditorRegex` (regex) |
130
132
  | `rule()`, `group()` + `rules_json()` | `Language(words=[WordGroup(...)], strings=..., ...)` + `Language.to_json()`; `HighlightRule` list for `EditorRegex` |
@@ -178,17 +180,17 @@ version = "1.0.0"
178
180
  requires-python = ">=3.10"
179
181
  dependencies = [
180
182
  "flet>=0.85.2",
181
- "flet-code-editor-dsl>=0.3.0",
183
+ "flet-code-editor-dsl>=0.3.2",
182
184
  ]
183
185
  ```
184
186
 
185
- Pin an exact version for reproducible builds: `"flet-code-editor-dsl==0.3.0"`. Upgrade with `pip install --upgrade flet-code-editor-dsl`.
187
+ Pin an exact version for reproducible builds: `"flet-code-editor-dsl==0.3.2"`. Upgrade with `pip install --upgrade flet-code-editor-dsl`.
186
188
 
187
189
  ### Option 2: GitHub
188
190
 
189
191
  ```bash
190
192
  pip install "git+https://github.com/obgwew/flet-code-editor-dsl.git"
191
- pip install "git+https://github.com/obgwew/flet-code-editor-dsl.git@v0.3.0" # pinned
193
+ pip install "git+https://github.com/obgwew/flet-code-editor-dsl.git@v0.3.2" # pinned
192
194
  ```
193
195
 
194
196
  Inside `pyproject.toml`:
@@ -445,13 +447,13 @@ Changing the language/rules, `syntax_highlighting`, `show_errors` or `code_foldi
445
447
 
446
448
  ## Mobile / Touch Features
447
449
 
448
- New in 0.3.0. They apply to both controls. Properties that take `None` mean **automatic**: enabled on Android/iOS, disabled elsewhere.
450
+ New in 0.3.2. They apply to both controls. Properties that take `None` mean **automatic**: enabled on Android/iOS, disabled elsewhere.
449
451
 
450
452
  | Property | Type | Default | Description |
451
453
  |----------|------|---------|-------------|
452
454
  | `selection_menu` | `bool` | `True` | Show the cut/copy/paste menu at the caret and selection handles (Android/iOS only). |
453
- | `selection_menu_items` | `list[str]` | `["cut","copy","paste","select_all"]` | Buttons of that menu. Also accepts `"undo"`, `"redo"`. |
454
- | `mobile_controls` | `bool \| None` | `None` (hidden) | Show the extra toolbar. Opt-in: `True` to show. |
455
+ | `selection_menu_items` | `list[str]` | `["cut","copy","paste","select_all"]` | Buttons of that menu, in order (see `ce.DEFAULT_SELECTION_MENU_ITEMS`). Also accepts `"undo"`, `"redo"`. Unknown ids are ignored. |
456
+ | `mobile_controls` | `bool \| None` | `None` (auto) | Show the extra toolbar. Auto = shown on Android/iOS, hidden elsewhere; `True` / `False` force it. |
455
457
  | `toolbar_items` | `list[str]` | all items | Toolbar buttons, see below. |
456
458
  | `toolbar_position` | `ToolbarPosition` | `BOTTOM` | `BOTTOM` or `TOP`. |
457
459
  | `cursor_pad` | `bool \| None` | `None` (auto) | Draggable pad inside the toolbar. Only visible when the toolbar is shown. |
@@ -474,11 +476,12 @@ ce.EditorTokens(
474
476
 
475
477
  - *Cut* and *Copy* appear only when something is selected. *Cut*, *Paste*, *Undo* and *Redo* are hidden in `read_only` mode.
476
478
  - The menu is shown on **Android and iOS only**. On desktop, the usual keyboard shortcuts apply.
477
- - Set `selection_menu=False` to disable it.
479
+ - Set `selection_menu=False` to disable it. The menu is rebuilt every time it opens, so changing `selection_menu_items` or `read_only` at runtime takes effect immediately.
480
+ - It works together with the optional toolbar: both use the same cut/copy/paste implementation (see [Paste behavior](#paste-behavior)).
478
481
 
479
482
  ### Extra toolbar and cursor pad
480
483
 
481
- An optional bar next to the editor, useful when you want explicit controls on a phone:
484
+ An extra bar next to the editor (arrows, undo/redo, home/end, tab, cursor pad). With the default `mobile_controls=None` it is **shown automatically on Android/iOS** and hidden on desktop; pass `True` or `False` to force it:
482
485
 
483
486
  ```python
484
487
  ce.EditorTokens(
@@ -640,7 +643,7 @@ sigils=[ce.Sigil("$", "#9CDCFE"), ce.Sigil("@", "#4FC1FF"), ce.Sigil("%", "#D7BA
640
643
 
641
644
  ### Numbers, operators, punctuation, identifiers
642
645
 
643
- **Numbers** (`numbers=True`): integers and decimals (`42`, `3.14`, `.5`), digit separators (`1_000_000`), exponents (`1e10`, `2.5E-3`), prefixed literals (`0x1F`, `0b1010`, `0o755`). A number ends where it ends: `10px` is the number `10` followed by the identifier `px`. Identifiers cannot start with a digit. Set `numbers=False` if digits should not be treated specially.
646
+ **Numbers** (`numbers=True`): integers and decimals (`42`, `3.14`, `.5`), digit separators (`1_000_000`), exponents (`1e10`, `2.5E-3`), prefixed literals (`0x1F` hex, `0b1010` binary, `0o755` octal; each prefix accepts only its own digits and `_`). A number ends where it ends: `10px` is the number `10` followed by the identifier `px`. Identifiers cannot start with a digit. Set `numbers=False` if digits should not be treated specially.
644
647
 
645
648
  **Operators** — each character in `Language.operators` is an operator character; a *run* of operator characters (`==`, `<=`, `&&`) becomes **one** token with `TokenColors.operator`.
646
649
 
@@ -711,7 +714,7 @@ errors=ce.ErrorRules(
711
714
  )
712
715
  ```
713
716
 
714
- > The lexer builds a message for each error (*Unterminated string*, *Unknown word: foo*, *Unmatched ')'*, *Unclosed '('*), but the editor only draws the underline; messages are not shown as tooltips yet. Brackets spanning several lines are **not** matched across lines; for a language where `{` and `}` regularly sit on different lines, leave the `{}` pair out.
717
+ > The lexer builds a message for each error (*Unterminated string*, *Unknown word: foo*, *Not allowed: goto*, *Unmatched ')'*, *Unclosed '('*), but the editor only draws the underline; messages are not shown as tooltips yet. Brackets spanning several lines are **not** matched across lines; for a language where `{` and `}` regularly sit on different lines, leave the `{}` pair out.
715
718
 
716
719
  ### `FoldRule` and `fold_by_indent` (code folding)
717
720
 
@@ -1086,7 +1089,7 @@ page.add(
1086
1089
  | Change | Rebuild needed? |
1087
1090
  |--------|-----------------|
1088
1091
  | Editing Python code, `value`, `language` / `Language(...)`, `rules`, colors, fonts, flags, sizes, layout, mobile options | No — sent to the client at runtime. |
1089
- | Updating `flet-code-editor-dsl` to a version whose Dart code changed (for example 0.2.x → 0.3.0) | **Yes** |
1092
+ | Updating `flet-code-editor-dsl` to a version whose Dart code changed (for example when upgrading to 0.3.2) | **Yes** |
1090
1093
  | Upgrading Flet itself to a new major/minor version | Yes |
1091
1094
  | Adding or removing other Flet extensions | Yes |
1092
1095
 
@@ -1133,7 +1136,7 @@ To test the library **before publishing it**:
1133
1136
  ```toml
1134
1137
  dependencies = [
1135
1138
  "flet>=0.85.2",
1136
- "flet-code-editor-dsl @ file:///C:/path/to/repo/dist/flet_code_editor_dsl-0.3.0-py3-none-any.whl",
1139
+ "flet-code-editor-dsl @ file:///C:/path/to/repo/dist/flet_code_editor_dsl-0.3.2-py3-none-any.whl",
1137
1140
  ]
1138
1141
  ```
1139
1142
 
@@ -1187,7 +1190,7 @@ flet-code-editor-dsl/
1187
1190
  ├── __init__.py
1188
1191
  └── flet_code_editor_dsl/
1189
1192
  ├── __init__.py
1190
- ├── pubspec.yaml # Flutter package (v0.3.0)
1193
+ ├── pubspec.yaml # Flutter package (v0.3.2)
1191
1194
  └── lib/
1192
1195
  ├── flet_code_editor_dsl.dart # Exports Extension
1193
1196
  └── src/
@@ -1221,7 +1224,7 @@ flet-code-editor-dsl/
1221
1224
 
1222
1225
  ## Known Limitations
1223
1226
 
1224
- - **Touch features are new in 0.3.0** and have had limited testing on real devices; please report problems with your device, OS version and Flet version.
1227
+ - **Touch features are new in 0.3.2** and have had limited testing on real devices; please report problems with your device, OS version and Flet version.
1225
1228
  - **The magnifier does not follow the selection handles** (they are owned by `re_editor`); it appears on a long press inside the text and follows the finger, not the caret.
1226
1229
  - **The selection menu is Android/iOS only.** Desktop keeps `re_editor`'s keyboard shortcuts.
1227
1230
  - **Pasting with the platform's built-in shortcut/menu inside `re_editor`** still uses its own code path; the library's paste normalization applies to its own menu and toolbar.
@@ -1241,13 +1244,13 @@ flet-code-editor-dsl/
1241
1244
  | Symptom | Likely cause and fix |
1242
1245
  |---------|----------------------|
1243
1246
  | `Unknown control: EditorRegex` / `EditorTokens` | The app is not running with the extension compiled in. Declare the library in `pyproject.toml` and run a build made with `flet build`. |
1244
- | `ImportError: cannot import name 'EditorRegex'` in the built app | The build packaged an older version (for example 0.2.0 from PyPI). See [Developing and Testing Locally](#developing-and-testing-locally): use a wheel file in `dependencies`, delete `build/`, rebuild, and check `build/site-packages/flet_code_editor_dsl/__init__.py`. |
1245
- | `TypeError` about `incremental_highlighting` | The argument was removed in 0.3.0; `EditorRegex` always highlights per line. Remove it. |
1247
+ | `ImportError: cannot import name 'EditorRegex'` in the built app | The build packaged an older version (an older release from PyPI). See [Developing and Testing Locally](#developing-and-testing-locally): use a wheel file in `dependencies`, delete `build/`, rebuild, and check `build/site-packages/flet_code_editor_dsl/__init__.py`. |
1248
+ | `TypeError` about `incremental_highlighting` | The argument no longer exists; `EditorRegex` always highlights per line. Remove it. |
1246
1249
  | `FletCodeEditor` / `FletCodeField` not found | They remain as deprecated aliases of `EditorTokens` / `EditorRegex`. If you removed the aliases, use the new names. |
1247
- | No cut/copy/paste menu on the phone | Make sure `selection_menu=True` (default), the app was **rebuilt** with 0.3.0, and the app runs on Android/iOS. The menu appears when you tap the caret, long-press, or select text. |
1250
+ | No cut/copy/paste menu on the phone | Make sure `selection_menu=True` (default), `selection_menu_items` is not empty, the app was **rebuilt** with 0.3.2 or newer, and the app runs on Android/iOS. The menu appears when you tap the caret, long-press, or select text. |
1248
1251
  | Pasted text does not appear | Use *Paste* from the selection menu or the toolbar (they sanitize the clipboard text). Check that the editor is not `read_only`. |
1249
1252
  | Magnifier does not appear | It is touch-only, needs a ~0.4 s long press inside the text area, and `magnifier` must not be `False`. |
1250
- | Cursor pad is missing | It lives in the toolbar: set `mobile_controls=True` (and keep `cursor_pad` not `False`). |
1253
+ | Cursor pad is missing | It lives in the toolbar: the toolbar must be visible (automatic on Android/iOS, or `mobile_controls=True`) and `cursor_pad` must not be `False`. |
1251
1254
  | The page does not scroll when dragging over the editor | Check `scroll_mode`. `PAGE_FIRST` (default) moves the page first; `EDITOR_ONLY` disables hand-off. The editor must be inside a vertical scrollable (`ListView`, `Column(scroll=...)`). |
1252
1255
  | The editor is tiny | `width_level` / `height_level` default to 13 (of 30). Set `expand=True`, `width`/`height`, or levels up to 30. |
1253
1256
  | No colors at all | `EditorTokens`: `language` is empty or not valid JSON — pass `Language(...).to_json()` (a string). `EditorRegex`: `rules` is empty or the patterns are invalid for Dart. Also check `syntax_highlighting=True`. |
@@ -12,7 +12,7 @@
12
12
  ## Table of Contents
13
13
 
14
14
  1. [Overview](#overview)
15
- 2. [What's New in 0.3.0 / Migration](#whats-new-in-030--migration)
15
+ 2. [What's New in 0.3.2 / Migration](#whats-new-in-032--migration)
16
16
  3. [Features](#features)
17
17
  4. [Requirements](#requirements)
18
18
  5. [Installation](#installation)
@@ -84,9 +84,9 @@ lang = ce.Language(
84
84
 
85
85
  and hand `lang.to_json()` to `EditorTokens`.
86
86
 
87
- ## What's New in 0.3.0 / Migration
87
+ ## What's New in 0.3.2 / Migration
88
88
 
89
- ### 0.3.0
89
+ ### 0.3.2
90
90
 
91
91
  | Change | Details |
92
92
  |--------|---------|
@@ -96,6 +96,8 @@ and hand `lang.to_json()` to `EditorTokens`.
96
96
  | **Touch support** | New selection menu at the caret/handles, optional toolbar and cursor pad, magnifier, `scroll_mode`. See [Mobile / Touch Features](#mobile--touch-features). |
97
97
  | **Paste fix** | Cut/copy/paste from the new menu/toolbar read the clipboard directly and normalize line endings and control characters before inserting. |
98
98
  | **New Dart files** | `regex_highlighter.dart` (regex engine). `code_editor.dart` is now shared by both controls. The old `src/flet_code_editor_dsl.dart` (`CodeField` widget) was deleted. |
99
+ | **Number literals** | `0b…` now accepts only `0`/`1` and `0o…` only `0`–`7` (before, they accepted any hex digit, so `0b1010f` was one number). `0x…` is unchanged. |
100
+ | **Sigils** | If the longest matching prefix has no name after it, shorter prefixes are tried next (for example `$$` and `$` defined together: a lone `$$ ` now falls back to `$`). |
99
101
 
100
102
  Rename in your code:
101
103
 
@@ -107,11 +109,11 @@ ce.FletCodeField(rules=[...]) ce.EditorRegex(rules=[...])
107
109
 
108
110
  Because the Dart side changed, **rebuild your app** after upgrading.
109
111
 
110
- ### 0.2.0 (from the original `CodeEditor` API)
112
+ ### Migrating from the original `CodeEditor` API
111
113
 
112
114
  The earlier regex-based `CodeEditor` control and its `rule()` / `group()` / `pair()` helpers no longer exist.
113
115
 
114
- | Original API | 0.2.0+ |
116
+ | Original API | 0.3.2 |
115
117
  |-------|-------|
116
118
  | Control `CodeEditor` | `EditorTokens` (tokenizer) and `EditorRegex` (regex) |
117
119
  | `rule()`, `group()` + `rules_json()` | `Language(words=[WordGroup(...)], strings=..., ...)` + `Language.to_json()`; `HighlightRule` list for `EditorRegex` |
@@ -165,17 +167,17 @@ version = "1.0.0"
165
167
  requires-python = ">=3.10"
166
168
  dependencies = [
167
169
  "flet>=0.85.2",
168
- "flet-code-editor-dsl>=0.3.0",
170
+ "flet-code-editor-dsl>=0.3.2",
169
171
  ]
170
172
  ```
171
173
 
172
- Pin an exact version for reproducible builds: `"flet-code-editor-dsl==0.3.0"`. Upgrade with `pip install --upgrade flet-code-editor-dsl`.
174
+ Pin an exact version for reproducible builds: `"flet-code-editor-dsl==0.3.2"`. Upgrade with `pip install --upgrade flet-code-editor-dsl`.
173
175
 
174
176
  ### Option 2: GitHub
175
177
 
176
178
  ```bash
177
179
  pip install "git+https://github.com/obgwew/flet-code-editor-dsl.git"
178
- pip install "git+https://github.com/obgwew/flet-code-editor-dsl.git@v0.3.0" # pinned
180
+ pip install "git+https://github.com/obgwew/flet-code-editor-dsl.git@v0.3.2" # pinned
179
181
  ```
180
182
 
181
183
  Inside `pyproject.toml`:
@@ -432,13 +434,13 @@ Changing the language/rules, `syntax_highlighting`, `show_errors` or `code_foldi
432
434
 
433
435
  ## Mobile / Touch Features
434
436
 
435
- New in 0.3.0. They apply to both controls. Properties that take `None` mean **automatic**: enabled on Android/iOS, disabled elsewhere.
437
+ New in 0.3.2. They apply to both controls. Properties that take `None` mean **automatic**: enabled on Android/iOS, disabled elsewhere.
436
438
 
437
439
  | Property | Type | Default | Description |
438
440
  |----------|------|---------|-------------|
439
441
  | `selection_menu` | `bool` | `True` | Show the cut/copy/paste menu at the caret and selection handles (Android/iOS only). |
440
- | `selection_menu_items` | `list[str]` | `["cut","copy","paste","select_all"]` | Buttons of that menu. Also accepts `"undo"`, `"redo"`. |
441
- | `mobile_controls` | `bool \| None` | `None` (hidden) | Show the extra toolbar. Opt-in: `True` to show. |
442
+ | `selection_menu_items` | `list[str]` | `["cut","copy","paste","select_all"]` | Buttons of that menu, in order (see `ce.DEFAULT_SELECTION_MENU_ITEMS`). Also accepts `"undo"`, `"redo"`. Unknown ids are ignored. |
443
+ | `mobile_controls` | `bool \| None` | `None` (auto) | Show the extra toolbar. Auto = shown on Android/iOS, hidden elsewhere; `True` / `False` force it. |
442
444
  | `toolbar_items` | `list[str]` | all items | Toolbar buttons, see below. |
443
445
  | `toolbar_position` | `ToolbarPosition` | `BOTTOM` | `BOTTOM` or `TOP`. |
444
446
  | `cursor_pad` | `bool \| None` | `None` (auto) | Draggable pad inside the toolbar. Only visible when the toolbar is shown. |
@@ -461,11 +463,12 @@ ce.EditorTokens(
461
463
 
462
464
  - *Cut* and *Copy* appear only when something is selected. *Cut*, *Paste*, *Undo* and *Redo* are hidden in `read_only` mode.
463
465
  - The menu is shown on **Android and iOS only**. On desktop, the usual keyboard shortcuts apply.
464
- - Set `selection_menu=False` to disable it.
466
+ - Set `selection_menu=False` to disable it. The menu is rebuilt every time it opens, so changing `selection_menu_items` or `read_only` at runtime takes effect immediately.
467
+ - It works together with the optional toolbar: both use the same cut/copy/paste implementation (see [Paste behavior](#paste-behavior)).
465
468
 
466
469
  ### Extra toolbar and cursor pad
467
470
 
468
- An optional bar next to the editor, useful when you want explicit controls on a phone:
471
+ An extra bar next to the editor (arrows, undo/redo, home/end, tab, cursor pad). With the default `mobile_controls=None` it is **shown automatically on Android/iOS** and hidden on desktop; pass `True` or `False` to force it:
469
472
 
470
473
  ```python
471
474
  ce.EditorTokens(
@@ -627,7 +630,7 @@ sigils=[ce.Sigil("$", "#9CDCFE"), ce.Sigil("@", "#4FC1FF"), ce.Sigil("%", "#D7BA
627
630
 
628
631
  ### Numbers, operators, punctuation, identifiers
629
632
 
630
- **Numbers** (`numbers=True`): integers and decimals (`42`, `3.14`, `.5`), digit separators (`1_000_000`), exponents (`1e10`, `2.5E-3`), prefixed literals (`0x1F`, `0b1010`, `0o755`). A number ends where it ends: `10px` is the number `10` followed by the identifier `px`. Identifiers cannot start with a digit. Set `numbers=False` if digits should not be treated specially.
633
+ **Numbers** (`numbers=True`): integers and decimals (`42`, `3.14`, `.5`), digit separators (`1_000_000`), exponents (`1e10`, `2.5E-3`), prefixed literals (`0x1F` hex, `0b1010` binary, `0o755` octal; each prefix accepts only its own digits and `_`). A number ends where it ends: `10px` is the number `10` followed by the identifier `px`. Identifiers cannot start with a digit. Set `numbers=False` if digits should not be treated specially.
631
634
 
632
635
  **Operators** — each character in `Language.operators` is an operator character; a *run* of operator characters (`==`, `<=`, `&&`) becomes **one** token with `TokenColors.operator`.
633
636
 
@@ -698,7 +701,7 @@ errors=ce.ErrorRules(
698
701
  )
699
702
  ```
700
703
 
701
- > The lexer builds a message for each error (*Unterminated string*, *Unknown word: foo*, *Unmatched ')'*, *Unclosed '('*), but the editor only draws the underline; messages are not shown as tooltips yet. Brackets spanning several lines are **not** matched across lines; for a language where `{` and `}` regularly sit on different lines, leave the `{}` pair out.
704
+ > The lexer builds a message for each error (*Unterminated string*, *Unknown word: foo*, *Not allowed: goto*, *Unmatched ')'*, *Unclosed '('*), but the editor only draws the underline; messages are not shown as tooltips yet. Brackets spanning several lines are **not** matched across lines; for a language where `{` and `}` regularly sit on different lines, leave the `{}` pair out.
702
705
 
703
706
  ### `FoldRule` and `fold_by_indent` (code folding)
704
707
 
@@ -1073,7 +1076,7 @@ page.add(
1073
1076
  | Change | Rebuild needed? |
1074
1077
  |--------|-----------------|
1075
1078
  | Editing Python code, `value`, `language` / `Language(...)`, `rules`, colors, fonts, flags, sizes, layout, mobile options | No — sent to the client at runtime. |
1076
- | Updating `flet-code-editor-dsl` to a version whose Dart code changed (for example 0.2.x → 0.3.0) | **Yes** |
1079
+ | Updating `flet-code-editor-dsl` to a version whose Dart code changed (for example when upgrading to 0.3.2) | **Yes** |
1077
1080
  | Upgrading Flet itself to a new major/minor version | Yes |
1078
1081
  | Adding or removing other Flet extensions | Yes |
1079
1082
 
@@ -1120,7 +1123,7 @@ To test the library **before publishing it**:
1120
1123
  ```toml
1121
1124
  dependencies = [
1122
1125
  "flet>=0.85.2",
1123
- "flet-code-editor-dsl @ file:///C:/path/to/repo/dist/flet_code_editor_dsl-0.3.0-py3-none-any.whl",
1126
+ "flet-code-editor-dsl @ file:///C:/path/to/repo/dist/flet_code_editor_dsl-0.3.2-py3-none-any.whl",
1124
1127
  ]
1125
1128
  ```
1126
1129
 
@@ -1174,7 +1177,7 @@ flet-code-editor-dsl/
1174
1177
  ├── __init__.py
1175
1178
  └── flet_code_editor_dsl/
1176
1179
  ├── __init__.py
1177
- ├── pubspec.yaml # Flutter package (v0.3.0)
1180
+ ├── pubspec.yaml # Flutter package (v0.3.2)
1178
1181
  └── lib/
1179
1182
  ├── flet_code_editor_dsl.dart # Exports Extension
1180
1183
  └── src/
@@ -1208,7 +1211,7 @@ flet-code-editor-dsl/
1208
1211
 
1209
1212
  ## Known Limitations
1210
1213
 
1211
- - **Touch features are new in 0.3.0** and have had limited testing on real devices; please report problems with your device, OS version and Flet version.
1214
+ - **Touch features are new in 0.3.2** and have had limited testing on real devices; please report problems with your device, OS version and Flet version.
1212
1215
  - **The magnifier does not follow the selection handles** (they are owned by `re_editor`); it appears on a long press inside the text and follows the finger, not the caret.
1213
1216
  - **The selection menu is Android/iOS only.** Desktop keeps `re_editor`'s keyboard shortcuts.
1214
1217
  - **Pasting with the platform's built-in shortcut/menu inside `re_editor`** still uses its own code path; the library's paste normalization applies to its own menu and toolbar.
@@ -1228,13 +1231,13 @@ flet-code-editor-dsl/
1228
1231
  | Symptom | Likely cause and fix |
1229
1232
  |---------|----------------------|
1230
1233
  | `Unknown control: EditorRegex` / `EditorTokens` | The app is not running with the extension compiled in. Declare the library in `pyproject.toml` and run a build made with `flet build`. |
1231
- | `ImportError: cannot import name 'EditorRegex'` in the built app | The build packaged an older version (for example 0.2.0 from PyPI). See [Developing and Testing Locally](#developing-and-testing-locally): use a wheel file in `dependencies`, delete `build/`, rebuild, and check `build/site-packages/flet_code_editor_dsl/__init__.py`. |
1232
- | `TypeError` about `incremental_highlighting` | The argument was removed in 0.3.0; `EditorRegex` always highlights per line. Remove it. |
1234
+ | `ImportError: cannot import name 'EditorRegex'` in the built app | The build packaged an older version (an older release from PyPI). See [Developing and Testing Locally](#developing-and-testing-locally): use a wheel file in `dependencies`, delete `build/`, rebuild, and check `build/site-packages/flet_code_editor_dsl/__init__.py`. |
1235
+ | `TypeError` about `incremental_highlighting` | The argument no longer exists; `EditorRegex` always highlights per line. Remove it. |
1233
1236
  | `FletCodeEditor` / `FletCodeField` not found | They remain as deprecated aliases of `EditorTokens` / `EditorRegex`. If you removed the aliases, use the new names. |
1234
- | No cut/copy/paste menu on the phone | Make sure `selection_menu=True` (default), the app was **rebuilt** with 0.3.0, and the app runs on Android/iOS. The menu appears when you tap the caret, long-press, or select text. |
1237
+ | No cut/copy/paste menu on the phone | Make sure `selection_menu=True` (default), `selection_menu_items` is not empty, the app was **rebuilt** with 0.3.2 or newer, and the app runs on Android/iOS. The menu appears when you tap the caret, long-press, or select text. |
1235
1238
  | Pasted text does not appear | Use *Paste* from the selection menu or the toolbar (they sanitize the clipboard text). Check that the editor is not `read_only`. |
1236
1239
  | Magnifier does not appear | It is touch-only, needs a ~0.4 s long press inside the text area, and `magnifier` must not be `False`. |
1237
- | Cursor pad is missing | It lives in the toolbar: set `mobile_controls=True` (and keep `cursor_pad` not `False`). |
1240
+ | Cursor pad is missing | It lives in the toolbar: the toolbar must be visible (automatic on Android/iOS, or `mobile_controls=True`) and `cursor_pad` must not be `False`. |
1238
1241
  | The page does not scroll when dragging over the editor | Check `scroll_mode`. `PAGE_FIRST` (default) moves the page first; `EDITOR_ONLY` disables hand-off. The editor must be inside a vertical scrollable (`ListView`, `Column(scroll=...)`). |
1239
1242
  | The editor is tiny | `width_level` / `height_level` default to 13 (of 30). Set `expand=True`, `width`/`height`, or levels up to 30. |
1240
1243
  | No colors at all | `EditorTokens`: `language` is empty or not valid JSON — pass `Language(...).to_json()` (a string). `EditorRegex`: `rules` is empty or the patterns are invalid for Dart. Also check `syntax_highlighting=True`. |
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "flet-code-editor-dsl"
7
- version = "0.3.1"
7
+ version = "0.3.2"
8
8
  description = "Flet code editors with syntax highlighting: EditorTokens (tokenizer) and EditorRegex (regex)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,4 +1,5 @@
1
1
  from flet_code_editor_dsl.flet_code_editor_dsl import (
2
+ DEFAULT_SELECTION_MENU_ITEMS,
2
3
  DEFAULT_TOOLBAR_ITEMS,
3
4
  EditorRegex,
4
5
  EditorTokens,
@@ -27,7 +28,8 @@ FletCodeField = EditorRegex
27
28
  __all__ = [
28
29
  "EditorRegex", "EditorTokens",
29
30
  "HighlightRule", "ErrorPattern",
30
- "VerticalMode", "ScrollMode", "ToolbarPosition", "DEFAULT_TOOLBAR_ITEMS",
31
+ "VerticalMode", "ScrollMode", "ToolbarPosition",
32
+ "DEFAULT_TOOLBAR_ITEMS", "DEFAULT_SELECTION_MENU_ITEMS",
31
33
  "Language", "WordGroup", "StringRule", "BlockComment", "Sigil",
32
34
  "TokenColors", "FoldRule", "ErrorRules", "BracketPair",
33
35
  "FletCodeEditor", "FletCodeField",
@@ -37,6 +37,9 @@ class ToolbarPosition(str, Enum):
37
37
  TOP = "top"
38
38
 
39
39
 
40
+ # Buttons of the floating selection menu (Android/iOS). Also accepted: "undo", "redo".
41
+ DEFAULT_SELECTION_MENU_ITEMS = ["cut", "copy", "paste", "select_all"]
42
+
40
43
  DEFAULT_TOOLBAR_ITEMS = [
41
44
  "undo", "redo", "cut", "copy", "paste", "select_all", "select_mode",
42
45
  "left", "right", "up", "down", "home", "end", "tab",
@@ -81,6 +84,8 @@ class EditorRegex(ft.LayoutControl):
81
84
  debounce_ms: int = 150
82
85
 
83
86
  # --- mobile (None = automatic: on for Android/iOS, off elsewhere) ---
87
+ selection_menu: bool = True # floating cut/copy/paste menu at the caret (Android/iOS)
88
+ selection_menu_items: list[str] = field(default_factory=lambda: list(DEFAULT_SELECTION_MENU_ITEMS))
84
89
  mobile_controls: bool | None = None # toolbar: cut/copy/paste/undo/arrows...
85
90
  toolbar_items: list[str] = field(default_factory=lambda: list(DEFAULT_TOOLBAR_ITEMS))
86
91
  toolbar_position: ToolbarPosition = ToolbarPosition.BOTTOM
@@ -125,6 +130,8 @@ class EditorTokens(ft.LayoutControl):
125
130
  debounce_ms: int = 150
126
131
 
127
132
  # --- mobile ---
133
+ selection_menu: bool = True
134
+ selection_menu_items: list[str] = field(default_factory=lambda: list(DEFAULT_SELECTION_MENU_ITEMS))
128
135
  mobile_controls: bool | None = None
129
136
  toolbar_items: list[str] = field(default_factory=lambda: list(DEFAULT_TOOLBAR_ITEMS))
130
137
  toolbar_position: ToolbarPosition = ToolbarPosition.BOTTOM
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flet-code-editor-dsl
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: Flet code editors with syntax highlighting: EditorTokens (tokenizer) and EditorRegex (regex)
5
5
  Author-email: obgwew <obgwew@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -25,7 +25,7 @@ Dynamic: license-file
25
25
  ## Table of Contents
26
26
 
27
27
  1. [Overview](#overview)
28
- 2. [What's New in 0.3.0 / Migration](#whats-new-in-030--migration)
28
+ 2. [What's New in 0.3.2 / Migration](#whats-new-in-032--migration)
29
29
  3. [Features](#features)
30
30
  4. [Requirements](#requirements)
31
31
  5. [Installation](#installation)
@@ -97,9 +97,9 @@ lang = ce.Language(
97
97
 
98
98
  and hand `lang.to_json()` to `EditorTokens`.
99
99
 
100
- ## What's New in 0.3.0 / Migration
100
+ ## What's New in 0.3.2 / Migration
101
101
 
102
- ### 0.3.0
102
+ ### 0.3.2
103
103
 
104
104
  | Change | Details |
105
105
  |--------|---------|
@@ -109,6 +109,8 @@ and hand `lang.to_json()` to `EditorTokens`.
109
109
  | **Touch support** | New selection menu at the caret/handles, optional toolbar and cursor pad, magnifier, `scroll_mode`. See [Mobile / Touch Features](#mobile--touch-features). |
110
110
  | **Paste fix** | Cut/copy/paste from the new menu/toolbar read the clipboard directly and normalize line endings and control characters before inserting. |
111
111
  | **New Dart files** | `regex_highlighter.dart` (regex engine). `code_editor.dart` is now shared by both controls. The old `src/flet_code_editor_dsl.dart` (`CodeField` widget) was deleted. |
112
+ | **Number literals** | `0b…` now accepts only `0`/`1` and `0o…` only `0`–`7` (before, they accepted any hex digit, so `0b1010f` was one number). `0x…` is unchanged. |
113
+ | **Sigils** | If the longest matching prefix has no name after it, shorter prefixes are tried next (for example `$$` and `$` defined together: a lone `$$ ` now falls back to `$`). |
112
114
 
113
115
  Rename in your code:
114
116
 
@@ -120,11 +122,11 @@ ce.FletCodeField(rules=[...]) ce.EditorRegex(rules=[...])
120
122
 
121
123
  Because the Dart side changed, **rebuild your app** after upgrading.
122
124
 
123
- ### 0.2.0 (from the original `CodeEditor` API)
125
+ ### Migrating from the original `CodeEditor` API
124
126
 
125
127
  The earlier regex-based `CodeEditor` control and its `rule()` / `group()` / `pair()` helpers no longer exist.
126
128
 
127
- | Original API | 0.2.0+ |
129
+ | Original API | 0.3.2 |
128
130
  |-------|-------|
129
131
  | Control `CodeEditor` | `EditorTokens` (tokenizer) and `EditorRegex` (regex) |
130
132
  | `rule()`, `group()` + `rules_json()` | `Language(words=[WordGroup(...)], strings=..., ...)` + `Language.to_json()`; `HighlightRule` list for `EditorRegex` |
@@ -178,17 +180,17 @@ version = "1.0.0"
178
180
  requires-python = ">=3.10"
179
181
  dependencies = [
180
182
  "flet>=0.85.2",
181
- "flet-code-editor-dsl>=0.3.0",
183
+ "flet-code-editor-dsl>=0.3.2",
182
184
  ]
183
185
  ```
184
186
 
185
- Pin an exact version for reproducible builds: `"flet-code-editor-dsl==0.3.0"`. Upgrade with `pip install --upgrade flet-code-editor-dsl`.
187
+ Pin an exact version for reproducible builds: `"flet-code-editor-dsl==0.3.2"`. Upgrade with `pip install --upgrade flet-code-editor-dsl`.
186
188
 
187
189
  ### Option 2: GitHub
188
190
 
189
191
  ```bash
190
192
  pip install "git+https://github.com/obgwew/flet-code-editor-dsl.git"
191
- pip install "git+https://github.com/obgwew/flet-code-editor-dsl.git@v0.3.0" # pinned
193
+ pip install "git+https://github.com/obgwew/flet-code-editor-dsl.git@v0.3.2" # pinned
192
194
  ```
193
195
 
194
196
  Inside `pyproject.toml`:
@@ -445,13 +447,13 @@ Changing the language/rules, `syntax_highlighting`, `show_errors` or `code_foldi
445
447
 
446
448
  ## Mobile / Touch Features
447
449
 
448
- New in 0.3.0. They apply to both controls. Properties that take `None` mean **automatic**: enabled on Android/iOS, disabled elsewhere.
450
+ New in 0.3.2. They apply to both controls. Properties that take `None` mean **automatic**: enabled on Android/iOS, disabled elsewhere.
449
451
 
450
452
  | Property | Type | Default | Description |
451
453
  |----------|------|---------|-------------|
452
454
  | `selection_menu` | `bool` | `True` | Show the cut/copy/paste menu at the caret and selection handles (Android/iOS only). |
453
- | `selection_menu_items` | `list[str]` | `["cut","copy","paste","select_all"]` | Buttons of that menu. Also accepts `"undo"`, `"redo"`. |
454
- | `mobile_controls` | `bool \| None` | `None` (hidden) | Show the extra toolbar. Opt-in: `True` to show. |
455
+ | `selection_menu_items` | `list[str]` | `["cut","copy","paste","select_all"]` | Buttons of that menu, in order (see `ce.DEFAULT_SELECTION_MENU_ITEMS`). Also accepts `"undo"`, `"redo"`. Unknown ids are ignored. |
456
+ | `mobile_controls` | `bool \| None` | `None` (auto) | Show the extra toolbar. Auto = shown on Android/iOS, hidden elsewhere; `True` / `False` force it. |
455
457
  | `toolbar_items` | `list[str]` | all items | Toolbar buttons, see below. |
456
458
  | `toolbar_position` | `ToolbarPosition` | `BOTTOM` | `BOTTOM` or `TOP`. |
457
459
  | `cursor_pad` | `bool \| None` | `None` (auto) | Draggable pad inside the toolbar. Only visible when the toolbar is shown. |
@@ -474,11 +476,12 @@ ce.EditorTokens(
474
476
 
475
477
  - *Cut* and *Copy* appear only when something is selected. *Cut*, *Paste*, *Undo* and *Redo* are hidden in `read_only` mode.
476
478
  - The menu is shown on **Android and iOS only**. On desktop, the usual keyboard shortcuts apply.
477
- - Set `selection_menu=False` to disable it.
479
+ - Set `selection_menu=False` to disable it. The menu is rebuilt every time it opens, so changing `selection_menu_items` or `read_only` at runtime takes effect immediately.
480
+ - It works together with the optional toolbar: both use the same cut/copy/paste implementation (see [Paste behavior](#paste-behavior)).
478
481
 
479
482
  ### Extra toolbar and cursor pad
480
483
 
481
- An optional bar next to the editor, useful when you want explicit controls on a phone:
484
+ An extra bar next to the editor (arrows, undo/redo, home/end, tab, cursor pad). With the default `mobile_controls=None` it is **shown automatically on Android/iOS** and hidden on desktop; pass `True` or `False` to force it:
482
485
 
483
486
  ```python
484
487
  ce.EditorTokens(
@@ -640,7 +643,7 @@ sigils=[ce.Sigil("$", "#9CDCFE"), ce.Sigil("@", "#4FC1FF"), ce.Sigil("%", "#D7BA
640
643
 
641
644
  ### Numbers, operators, punctuation, identifiers
642
645
 
643
- **Numbers** (`numbers=True`): integers and decimals (`42`, `3.14`, `.5`), digit separators (`1_000_000`), exponents (`1e10`, `2.5E-3`), prefixed literals (`0x1F`, `0b1010`, `0o755`). A number ends where it ends: `10px` is the number `10` followed by the identifier `px`. Identifiers cannot start with a digit. Set `numbers=False` if digits should not be treated specially.
646
+ **Numbers** (`numbers=True`): integers and decimals (`42`, `3.14`, `.5`), digit separators (`1_000_000`), exponents (`1e10`, `2.5E-3`), prefixed literals (`0x1F` hex, `0b1010` binary, `0o755` octal; each prefix accepts only its own digits and `_`). A number ends where it ends: `10px` is the number `10` followed by the identifier `px`. Identifiers cannot start with a digit. Set `numbers=False` if digits should not be treated specially.
644
647
 
645
648
  **Operators** — each character in `Language.operators` is an operator character; a *run* of operator characters (`==`, `<=`, `&&`) becomes **one** token with `TokenColors.operator`.
646
649
 
@@ -711,7 +714,7 @@ errors=ce.ErrorRules(
711
714
  )
712
715
  ```
713
716
 
714
- > The lexer builds a message for each error (*Unterminated string*, *Unknown word: foo*, *Unmatched ')'*, *Unclosed '('*), but the editor only draws the underline; messages are not shown as tooltips yet. Brackets spanning several lines are **not** matched across lines; for a language where `{` and `}` regularly sit on different lines, leave the `{}` pair out.
717
+ > The lexer builds a message for each error (*Unterminated string*, *Unknown word: foo*, *Not allowed: goto*, *Unmatched ')'*, *Unclosed '('*), but the editor only draws the underline; messages are not shown as tooltips yet. Brackets spanning several lines are **not** matched across lines; for a language where `{` and `}` regularly sit on different lines, leave the `{}` pair out.
715
718
 
716
719
  ### `FoldRule` and `fold_by_indent` (code folding)
717
720
 
@@ -1086,7 +1089,7 @@ page.add(
1086
1089
  | Change | Rebuild needed? |
1087
1090
  |--------|-----------------|
1088
1091
  | Editing Python code, `value`, `language` / `Language(...)`, `rules`, colors, fonts, flags, sizes, layout, mobile options | No — sent to the client at runtime. |
1089
- | Updating `flet-code-editor-dsl` to a version whose Dart code changed (for example 0.2.x → 0.3.0) | **Yes** |
1092
+ | Updating `flet-code-editor-dsl` to a version whose Dart code changed (for example when upgrading to 0.3.2) | **Yes** |
1090
1093
  | Upgrading Flet itself to a new major/minor version | Yes |
1091
1094
  | Adding or removing other Flet extensions | Yes |
1092
1095
 
@@ -1133,7 +1136,7 @@ To test the library **before publishing it**:
1133
1136
  ```toml
1134
1137
  dependencies = [
1135
1138
  "flet>=0.85.2",
1136
- "flet-code-editor-dsl @ file:///C:/path/to/repo/dist/flet_code_editor_dsl-0.3.0-py3-none-any.whl",
1139
+ "flet-code-editor-dsl @ file:///C:/path/to/repo/dist/flet_code_editor_dsl-0.3.2-py3-none-any.whl",
1137
1140
  ]
1138
1141
  ```
1139
1142
 
@@ -1187,7 +1190,7 @@ flet-code-editor-dsl/
1187
1190
  ├── __init__.py
1188
1191
  └── flet_code_editor_dsl/
1189
1192
  ├── __init__.py
1190
- ├── pubspec.yaml # Flutter package (v0.3.0)
1193
+ ├── pubspec.yaml # Flutter package (v0.3.2)
1191
1194
  └── lib/
1192
1195
  ├── flet_code_editor_dsl.dart # Exports Extension
1193
1196
  └── src/
@@ -1221,7 +1224,7 @@ flet-code-editor-dsl/
1221
1224
 
1222
1225
  ## Known Limitations
1223
1226
 
1224
- - **Touch features are new in 0.3.0** and have had limited testing on real devices; please report problems with your device, OS version and Flet version.
1227
+ - **Touch features are new in 0.3.2** and have had limited testing on real devices; please report problems with your device, OS version and Flet version.
1225
1228
  - **The magnifier does not follow the selection handles** (they are owned by `re_editor`); it appears on a long press inside the text and follows the finger, not the caret.
1226
1229
  - **The selection menu is Android/iOS only.** Desktop keeps `re_editor`'s keyboard shortcuts.
1227
1230
  - **Pasting with the platform's built-in shortcut/menu inside `re_editor`** still uses its own code path; the library's paste normalization applies to its own menu and toolbar.
@@ -1241,13 +1244,13 @@ flet-code-editor-dsl/
1241
1244
  | Symptom | Likely cause and fix |
1242
1245
  |---------|----------------------|
1243
1246
  | `Unknown control: EditorRegex` / `EditorTokens` | The app is not running with the extension compiled in. Declare the library in `pyproject.toml` and run a build made with `flet build`. |
1244
- | `ImportError: cannot import name 'EditorRegex'` in the built app | The build packaged an older version (for example 0.2.0 from PyPI). See [Developing and Testing Locally](#developing-and-testing-locally): use a wheel file in `dependencies`, delete `build/`, rebuild, and check `build/site-packages/flet_code_editor_dsl/__init__.py`. |
1245
- | `TypeError` about `incremental_highlighting` | The argument was removed in 0.3.0; `EditorRegex` always highlights per line. Remove it. |
1247
+ | `ImportError: cannot import name 'EditorRegex'` in the built app | The build packaged an older version (an older release from PyPI). See [Developing and Testing Locally](#developing-and-testing-locally): use a wheel file in `dependencies`, delete `build/`, rebuild, and check `build/site-packages/flet_code_editor_dsl/__init__.py`. |
1248
+ | `TypeError` about `incremental_highlighting` | The argument no longer exists; `EditorRegex` always highlights per line. Remove it. |
1246
1249
  | `FletCodeEditor` / `FletCodeField` not found | They remain as deprecated aliases of `EditorTokens` / `EditorRegex`. If you removed the aliases, use the new names. |
1247
- | No cut/copy/paste menu on the phone | Make sure `selection_menu=True` (default), the app was **rebuilt** with 0.3.0, and the app runs on Android/iOS. The menu appears when you tap the caret, long-press, or select text. |
1250
+ | No cut/copy/paste menu on the phone | Make sure `selection_menu=True` (default), `selection_menu_items` is not empty, the app was **rebuilt** with 0.3.2 or newer, and the app runs on Android/iOS. The menu appears when you tap the caret, long-press, or select text. |
1248
1251
  | Pasted text does not appear | Use *Paste* from the selection menu or the toolbar (they sanitize the clipboard text). Check that the editor is not `read_only`. |
1249
1252
  | Magnifier does not appear | It is touch-only, needs a ~0.4 s long press inside the text area, and `magnifier` must not be `False`. |
1250
- | Cursor pad is missing | It lives in the toolbar: set `mobile_controls=True` (and keep `cursor_pad` not `False`). |
1253
+ | Cursor pad is missing | It lives in the toolbar: the toolbar must be visible (automatic on Android/iOS, or `mobile_controls=True`) and `cursor_pad` must not be `False`. |
1251
1254
  | The page does not scroll when dragging over the editor | Check `scroll_mode`. `PAGE_FIRST` (default) moves the page first; `EDITOR_ONLY` disables hand-off. The editor must be inside a vertical scrollable (`ListView`, `Column(scroll=...)`). |
1252
1255
  | The editor is tiny | `width_level` / `height_level` default to 13 (of 30). Set `expand=True`, `width`/`height`, or levels up to 30. |
1253
1256
  | No colors at all | `EditorTokens`: `language` is empty or not valid JSON — pass `Language(...).to_json()` (a string). `EditorRegex`: `rules` is empty or the patterns are invalid for Dart. Also check `syntax_highlighting=True`. |
@@ -83,6 +83,8 @@ const List<String> _defaultToolbar = [
83
83
  "left", "right", "up", "down", "home", "end", "tab",
84
84
  ];
85
85
 
86
+ const List<String> _defaultSelectionMenu = ["cut", "copy", "paste", "select_all"];
87
+
86
88
  class _FletEditorControlState extends State<FletEditorControl> {
87
89
  late final CodeLineEditingController _controller;
88
90
  Timer? _debounce;
@@ -111,6 +113,66 @@ class _FletEditorControlState extends State<FletEditorControl> {
111
113
  int? _pointer;
112
114
  final ValueNotifier<Offset?> _magnifierAt = ValueNotifier<Offset?>(null);
113
115
 
116
+ // Floating cut/copy/paste menu (re_editor only shows one when it is given a
117
+ // toolbar controller). Only used on Android/iOS.
118
+ late final MobileSelectionToolbarController _menuController =
119
+ MobileSelectionToolbarController(builder: _menuBuilder);
120
+
121
+ Widget _menuBuilder({
122
+ required BuildContext context,
123
+ required TextSelectionToolbarAnchors anchors,
124
+ required CodeLineEditingController controller,
125
+ required VoidCallback onDismiss,
126
+ required VoidCallback onRefresh,
127
+ }) {
128
+ final readOnly = widget.control.getBool("read_only", false)!;
129
+ final raw = widget.control.get("selection_menu_items");
130
+ final ids = raw is List
131
+ ? [for (final i in raw) i.toString()]
132
+ : _defaultSelectionMenu;
133
+ final loc = MaterialLocalizations.of(context);
134
+ final hasSelection = controller.selectedText.isNotEmpty;
135
+
136
+ final items = <ContextMenuButtonItem>[];
137
+ void add(String label, VoidCallback run) {
138
+ items.add(ContextMenuButtonItem(
139
+ label: label,
140
+ onPressed: () {
141
+ run();
142
+ onDismiss();
143
+ },
144
+ ));
145
+ }
146
+
147
+ for (final id in ids) {
148
+ switch (id) {
149
+ case "cut":
150
+ if (!readOnly && hasSelection) add(loc.cutButtonLabel, () => _cut());
151
+ break;
152
+ case "copy":
153
+ if (hasSelection) add(loc.copyButtonLabel, () => _copy());
154
+ break;
155
+ case "paste":
156
+ if (!readOnly) add(loc.pasteButtonLabel, () => _paste());
157
+ break;
158
+ case "select_all":
159
+ add(loc.selectAllButtonLabel, () => _controller.selectAll());
160
+ break;
161
+ case "undo":
162
+ if (!readOnly) add("Undo", () => _controller.undo());
163
+ break;
164
+ case "redo":
165
+ if (!readOnly) add("Redo", () => _controller.redo());
166
+ break;
167
+ }
168
+ }
169
+ if (items.isEmpty) return const SizedBox.shrink();
170
+ return AdaptiveTextSelectionToolbar.buttonItems(
171
+ anchors: anchors,
172
+ buttonItems: items,
173
+ );
174
+ }
175
+
114
176
  bool get _isMobilePlatform =>
115
177
  defaultTargetPlatform == TargetPlatform.android ||
116
178
  defaultTargetPlatform == TargetPlatform.iOS;
@@ -132,6 +194,7 @@ class _FletEditorControlState extends State<FletEditorControl> {
132
194
  void dispose() {
133
195
  _debounce?.cancel();
134
196
  _lpTimer?.cancel();
197
+ _menuController.hide(context);
135
198
  _magnifierAt.dispose();
136
199
  _controller.removeListener(_onControllerChanged);
137
200
  _controller.dispose();
@@ -576,6 +639,7 @@ class _FletEditorControlState extends State<FletEditorControl> {
576
639
  ? [for (final i in itemsRaw) i.toString()]
577
640
  : _defaultToolbar;
578
641
  final scrollMode = control.getString("scroll_mode", "page_first")!;
642
+ final showMenu = mobile && control.getBool("selection_menu", true)!;
579
643
 
580
644
  Widget editor = CodeEditor(
581
645
  key: ValueKey("editor_$_epoch"),
@@ -584,6 +648,7 @@ class _FletEditorControlState extends State<FletEditorControl> {
584
648
  wordWrap: wrap,
585
649
  padding: const EdgeInsets.all(4),
586
650
  onChanged: _handleChanged,
651
+ toolbarController: showMenu ? _menuController : null,
587
652
  chunkAnalyzer: _chunkAnalyzer,
588
653
  style: CodeEditorStyle(
589
654
  fontFamily: fontFamily,
@@ -460,8 +460,8 @@ class CodeLanguage {
460
460
  add(pos, e, s.color);
461
461
  pos = e;
462
462
  matched = true;
463
+ break;
463
464
  }
464
- break;
465
465
  }
466
466
  }
467
467
  if (matched) continue;
@@ -476,7 +476,16 @@ class CodeLanguage {
476
476
  (next == 120 || next == 88 || next == 98 || next == 66 ||
477
477
  next == 111 || next == 79)) {
478
478
  e += 2;
479
- while (e < n && (_isHex(line.codeUnitAt(e)) || line.codeUnitAt(e) == 95)) {
479
+ final isHexLit = next == 120 || next == 88;
480
+ final isBinLit = next == 98 || next == 66;
481
+ bool digitOk(int c) =>
482
+ c == 95 ||
483
+ (isHexLit
484
+ ? _isHex(c)
485
+ : isBinLit
486
+ ? (c == 48 || c == 49)
487
+ : (c >= 48 && c <= 55));
488
+ while (e < n && digitOk(line.codeUnitAt(e))) {
480
489
  e++;
481
490
  }
482
491
  } else {
@@ -1,6 +1,6 @@
1
1
  name: flet_code_editor_dsl
2
2
  description: Flet code editors with syntax highlighting (EditorTokens / EditorRegex)
3
- version: 0.3.0
3
+ version: 0.3.2
4
4
  publish_to: none
5
5
 
6
6
  environment: