Editor
A code editor with syntax highlighting in the theme colors (100+ languages), line numbers, git markers, auto-closing pairs, folding, a minimap and font zoom. It is uncontrolled: the text, cursor and undo history live in Rust, tied to id, and text is only the initial value. on_change receives the full text and on_cursor the (line, column). pz.code_editor is the base widget without the theme.
ui.editor · Category: Code and tools · Full reference →


code = '''import pyzed as pzfrom pyzed import ui
class Counter(pz.App): def __init__(self): self.count = 0
def view(self): return ui.button(f"Clicks: {self.count}", self.increment)'''pz.container(ui.editor("counter.py", code, path="counter.py", markers={7: "modified", 10: "created"}), width=620, height=290)When to use
Section titled “When to use”- For code, configuration files, logs you can edit, or any long text.
- Use the file path as
id: each file keeps its cursor and history when you switch tabs. - To replace the text from code, return
pz.Command.set_editor_text(id, text).
import pyzed as pzfrom pyzed import ui
from pathlib import Path
class Editor(pz.App): def __init__(self): self.path = "main.py" self.text = Path(self.path).read_text()
def save(self): Path(self.path).write_text(self.text)
def view(self): return ui.editor(self.path, self.text, path=self.path, on_change=lambda text: setattr(self, "text", text))Variants
Section titled “Variants”Language
Section titled “Language”

path="counter.py"Code
pz.container(ui.editor("v-py", "class Counter(pz.App):\n count = 0\n\n def view(self):\n return ui.button('Add', self.add)", path="counter.py"), width=470, height=110)

language="rust"Code
pz.container(ui.editor("v-rs", "fn main() {\n println!(\"hi\");\n}\n", language="rust"), width=420, height=90)

language="json"Code
pz.container(ui.editor("v-json", '{\n "name": "notes",\n "version": 2\n}\n', language="json"), width=420, height=110)Options
Section titled “Options”

gutter=FalseCode
pz.container(ui.editor("v-g", "class Counter(pz.App):\n count = 0\n\n def view(self):\n return ui.button('Add', self.add)", path="a.py", gutter=False), width=470, height=110)

markers=Code
pz.container(ui.editor("v-m", "class Counter(pz.App):\n count = 0\n\n def view(self):\n return ui.button('Add', self.add)", path="a.py", markers={2: "created", 5: "modified"}), width=470, height=110)

minimap=TrueCode
pz.container(ui.editor("v-mm", "class Counter(pz.App):\n count = 0\n\n def view(self):\n return ui.button('Add', self.add)", path="a.py", minimap=True), width=470, height=124)

show_whitespace=TrueCode
pz.container(ui.editor("v-ws", "class Counter(pz.App):\n count = 0\n\n def view(self):\n return ui.button('Add', self.add)", path="a.py", show_whitespace=True), width=470, height=110)

placeholder=Code
pz.container(ui.editor("v-ph", "", placeholder="Write something…"), width=420, height=60)

font_size=16Code
pz.container(ui.editor("v-fs", "print(\"big\")\n", path="a.py", font_size=16), width=420, height=60)Examples
Section titled “Examples”Folding, code lens and minimap
Section titled “Folding, code lens and minimap”Blocks fold by indentation (Ctrl+Shift+[ and ]), annotations adds a code lens above a line and minimap=True draws the overview on the right.


code = '''import pyzed as pzfrom pyzed import ui
class Counter(pz.App): def __init__(self): self.count = 0
def increment(self): self.count += 1
def view(self): return ui.button(f"Clicks: {self.count}", self.increment)'''pz.container(ui.editor("lens.py", code, path="counter.py", minimap=True, annotations={5: "1 reference"}), width=680, height=290)Cursor and whitespace
Section titled “Cursor and whitespace”cursor_shape is "bar", "block", "underline" or "hollow"; show_whitespace=True draws spaces and tabs; wrap=True wraps long lines.


pz.container(ui.editor("ws.py", "def greet(name):\n return f'Hello, {name}'\n", path="ws.py", cursor_shape="block", show_whitespace=True, font_size=15), width=620, height=120)Events
Section titled “Events”Editor has 6 events of its own, listed below. Like every widget it also has the 18 common events (click, double_click, right_click, mouse_enter, drag, key_down, resize…), attached with .on(...): see Events and Events of every component.
| Event | Of | Handler gets | When |
|---|---|---|---|
on_change |
ui.editor, pz.code_editor |
(text) |
Callable that receives the new value. |
on_cursor |
ui.editor, pz.code_editor |
(line, column) |
Callable that receives (line, column). |
on_scroll |
ui.editor, pz.code_editor |
(info) |
Called on scroll. |
on_zoom |
ui.editor, pz.code_editor |
(step) |
Callable that receives 1, -1 or 0 for Ctrl+= / Ctrl+- / Ctrl+0 and Ctrl+wheel. |
on_action |
ui.editor, pz.code_editor |
(name) |
Callable that receives the name of each editor action that runs ("undo", "select_next"…), e.g. to count them. |
on_hover |
ui.editor, pz.code_editor |
() |
Callable that receives {line, column, start, end, x, y, height} (the word under the mouse, from 1, and its place in the editor) after the mouse rests on it, and None when it leaves (hover cards). |
Handler gets is what Pyzed passes to your callable: () means nothing. Any handler can also be a message (a value that is not callable), which goes to update().
Handling the events
Section titled “Handling the events”The same events written three ways. Imperative: methods of the app change self. Declarative: the handlers produce messages and one update() decides. Functional: a pure function draws an immutable state and asks for changes with set_state(...). See Imperative, declarative and functional.
class Editor(pz.App): def __init__(self): self.text = "print('hello')\n" self.cursor = (1, 1) self.font_size = 14
def zoom(self, step): # on_zoom: 1, -1 or 0 (Ctrl+=, Ctrl+-, Ctrl+0) self.font_size = 14 if step == 0 else self.font_size + step
def view(self): line, column = self.cursor return pz.column([ ui.editor("main.py", self.text, path="main.py", font_size=self.font_size, height=200, on_change=lambda text: setattr(self, "text", text), # every edit on_cursor=lambda ln, col: setattr(self, "cursor", (ln, col)), # from 1 on_zoom=self.zoom, on_action=lambda name: print("ran", name)), # "undo"... ui.status_bar([], [ui.status_item(f"Ln {line}, Col {column}")]), ])from dataclasses import dataclass
@dataclassclass Edited: text: str
@dataclassclass Moved: line: int column: int
class Editor(pz.App): text, cursor = "print('hello')\n", (1, 1)
def update(self, message): match message: case Edited(text): self.text = text case Moved(line, column): self.cursor = (line, column)
def view(self): return ui.editor("main.py", self.text, path="main.py", height=200, on_change=Edited, on_cursor=Moved) # the classes build the messagesfrom dataclasses import dataclass
@dataclass(frozen=True)class State: text: str = "print('hello')\n" line: int = 1 column: int = 1
def view(state, set_state): return pz.column([ ui.editor("main.py", state.text, path="main.py", height=200, on_change=lambda text: set_state(text=text), on_cursor=lambda line, column: set_state(line=line, column=column)), ui.label(f"Ln {state.line}, Col {state.column}"), ])Properties and API
Section titled “Properties and API”ui.editor
Section titled “ui.editor”editor( id, text='', *, language=None, path=None, on_change=None, on_cursor=None, markers=None, font_size=None, line_height=None, gutter=True, wrap=False, active_line=True, height='fill', placeholder=None, annotations=None, show_whitespace=False, tab_size=None, hard_tabs=False, backspace_unindent=True, repeat_delay=None, repeat_rate=None, capture_keys=(), on_scroll=None, auto_close=True, folding=True, minimap=False, cursor_shape='bar', cursor_blink=True, cursor_width=2.0, cursor_color=None, on_zoom=None, on_action=None, highlights=None, match_brackets=True, selection_highlight=True, font=None, keymap=None, scrollbar=True, readonly=False, on_hover=None, hover_delay=500, sticky_scroll=0, theme=None,)A code editor: highlighting with the theme colors, line numbers and git markers.
| Property | Default | Description |
|---|---|---|
id |
required | Identifies the buffer (use the file path). |
text |
"" |
Initial text. |
language |
None |
Language. If missing, it is inferred from path. |
path |
None |
File path. |
markers |
None |
{line: "created" | "modified" | "deleted"}. |
font_size |
None |
Font size (defaults to the theme’s). |
line_height |
None |
Line height. |
gutter |
True |
Shows line numbers. |
wrap |
False |
Line wrapping. |
active_line |
True |
Background color of the cursor line. |
height |
"fill" |
Height: pixels, "fill", "shrink" or "fill:N" (proportion). |
placeholder |
None |
Hint text shown when empty. |
annotations |
None |
{line: "text"} or {line: ("text", color)}: virtual text at the end of the line (code lens, diagnostics). |
show_whitespace |
False |
Draws spaces as · and tabs as →. |
tab_size |
None |
Tab inserts spaces up to the next multiple; Enter keeps the indentation (one more level after :); Backspace removes a level. |
hard_tabs |
False |
With tab_size: Tab, Enter and indent (Ctrl+]) use tab characters instead of spaces. |
backspace_unindent |
True |
With tab_size: Backspace in leading spaces removes a whole level (False: one space). |
repeat_delay |
None |
Milliseconds Backspace and Delete wait, held down, before repeating (None: the system’s). |
repeat_rate |
None |
Deletions per second at most while Backspace or Delete is held down (None: the system’s pace). |
capture_keys |
() |
Keys the editor leaves to the app’s on_key ("up", "enter"…), e.g. while a completion list is open. |
auto_close |
True |
Closes brackets and quotes as you type (and wraps the selection). |
folding |
True |
Fold chevrons in the gutter; Ctrl+Shift+[ folds and Ctrl+Shift+] unfolds. |
minimap |
False |
True (or a width in pixels) shows a minimap on the right. |
cursor_shape |
"bar" |
"bar", "block", "underline" or "hollow". |
cursor_blink |
True |
Whether the cursor blinks. |
cursor_width |
2.0 |
Width of the bar cursor. |
cursor_color |
None |
Cursor color (the theme’s player color by default). |
highlights |
None |
Ranges painted behind the text in the theme’s search color: [(line, column, end_line, end_column)], from 1, with exclusive ends. |
match_brackets |
True |
Outlines the bracket that matches the one next to the cursor (Ctrl+M jumps to it). |
selection_highlight |
True |
Highlights the other occurrences of the selected text (Ctrl+D adds the next one as a cursor). |
font |
None |
Typeface: "mono" by default; "sans" makes a multi-line text box, like a chat’s message box. |
keymap |
None |
Zed-style {binding: action} dict ({"ctrl-shift-d": "duplicate_line_down"}); None as the action removes a default key. Build it from per-action overrides with pyzed.ui.editor.keymap_for. |
scrollbar |
True |
False hides the scrollbars. |
readonly |
False |
True lets the text be selected and copied but not changed (a log, a traceback). |
hover_delay |
500 |
Milliseconds the mouse rests on a word before on_hover is called. |
sticky_scroll |
0 |
How many lines of the enclosing blocks (class, def, if…) stay pinned at the top while scrolling (0: none). |
theme |
None |
Theme to use instead of the current one (pyzed.theme.current()). |
Events: on_change, on_cursor, on_scroll, on_zoom, on_action, on_hover (events).
ui.language_token
Section titled “ui.language_token”language_token(path)Returns the highlighter language token for a path ("main.rs" → "rs").
| Property | Default | Description |
|---|---|---|
path |
required | File path. |
pz.code_editor
Section titled “pz.code_editor”code_editor( id, text='', *, language='txt', size=14.0, line_height=None, font=None, width=None, height=None, padding=None, syntax=None, bg=None, color=None, selection_color=None, placeholder=None, placeholder_color=None, gutter=True, gutter_color=None, gutter_active_color=None, gutter_width=None, markers=None, wrap=False, on_change=None, on_cursor=None, active_line=None, scrollbar_color=None, annotations=None, whitespace=None, tab_size=None, capture_keys=None, on_scroll=None, auto_close=False, folding=False, minimap=None, minimap_thumb=None, cursor_shape='bar', cursor_width=2.0, cursor_blink=True, cursor_color=None, on_zoom=None, on_action=None, highlights=None, highlight_color=None, match_brackets=True, selection_highlight=True, keymap=None, scrollbar=True, readonly=False, hard_tabs=False, backspace_unindent=True, repeat_delay=None, repeat_rate=None, on_hover=None, hover_delay=500.0, sticky_scroll=0,)A code editor with syntax highlighting, line numbers and git markers, based on Iced’s
text_editor. It is uncontrolled: text is only the initial value for that id; the
text, cursor and history live in Rust. Use Command.set_editor_text to replace it.
For the themed editor use ui.editor.
| Property | Default | Description |
|---|---|---|
id |
required | Identifies the buffer. Reuse it to keep state across renders. |
text |
"" |
Initial text. |
language |
"txt" |
Language extension or name ("py", "rs", "json"…). |
size |
14.0 |
Font size. |
line_height |
None |
Line height in pixels. |
font |
None |
Family (monospace by default). |
width |
None |
Width: pixels, "fill", "shrink" or "fill:N" (proportion). |
height |
None |
Height: pixels, "fill", "shrink" or "fill:N" (proportion). |
padding |
None |
Inner padding: 8, (vertical, horizontal) or (top, right, bottom, left). |
syntax |
None |
Map of TextMate scopes to colors (provided by Theme.syntax_scopes()). |
bg |
None |
Background color ("#rrggbb[aa]", (r, g, b[, a]) or "transparent"). |
color |
None |
Text or icon color. |
selection_color |
None |
Selection color. |
placeholder |
None |
Hint text shown when empty. |
placeholder_color |
None |
Placeholder color. |
gutter |
True |
Shows line numbers. |
gutter_color |
None |
Line number color. |
gutter_active_color |
None |
Color of the cursor line’s number. |
gutter_width |
None |
Gutter width (automatic by default). |
markers |
None |
{line: color} for git markers in the gutter (lines from 1). |
wrap |
False |
Line wrapping. |
active_line |
None |
Background color of the cursor line. |
scrollbar_color |
None |
Scrollbar color. |
annotations |
None |
{line: "text"} or {line: ("text", color)}: virtual text at the end of the line (code lens, diagnostics). |
whitespace |
None |
Draws spaces as · and tabs as → in this color. |
tab_size |
None |
Tab inserts spaces up to the next multiple; Enter keeps the indentation; Backspace removes a level. |
capture_keys |
None |
Keys the editor leaves to the app’s on_key ("up", "enter"…), e.g. while a completion list is open. |
auto_close |
False |
Typing a bracket or quote also inserts its closing pair. |
folding |
False |
Fold chevrons in the gutter and Ctrl+Shift+[ / ]. |
minimap |
None |
Width of the minimap in pixels (None: no minimap). |
minimap_thumb |
None |
Color of the minimap’s visible-area highlight. |
cursor_shape |
"bar" |
"bar", "block", "underline" or "hollow". |
cursor_width |
2.0 |
Width of the bar cursor. |
cursor_blink |
True |
Whether the cursor blinks. |
cursor_color |
None |
Cursor color. |
highlights |
None |
Ranges painted behind the text (search results): [(line, column, end_line, end_column)], from 1, with exclusive ends. |
highlight_color |
None |
Color of highlights. |
match_brackets |
True |
Outlines the bracket that matches the one next to the cursor. |
selection_highlight |
True |
Highlights the other occurrences of the selected text. |
keymap |
None |
Zed-style {binding: action} dict; None as the action removes a default key (pyzed.ui.editor.keymap_for builds one from per-action overrides). |
scrollbar |
True |
False hides the scrollbars. |
readonly |
False |
True lets the text be selected and copied but not changed (a log, a traceback). |
hard_tabs |
False |
With tab_size: Tab, Enter and indent (Ctrl+]) use tab characters instead of spaces. |
backspace_unindent |
True |
With tab_size: Backspace in leading spaces removes a whole level (False: one space). |
repeat_delay |
None |
Milliseconds Backspace and Delete wait, held down, before repeating (None: the system’s). |
repeat_rate |
None |
Deletions per second at most while Backspace or Delete is held down (None: the system’s pace). |
hover_delay |
500.0 |
Milliseconds the mouse rests on a word before on_hover is called. |
sticky_scroll |
0 |
How many lines of the enclosing blocks (class, def, if…) stay pinned at the top while scrolling (0: none). |
Events: on_change, on_cursor, on_scroll, on_zoom, on_action, on_hover (events).