Ir al contenido

Código

Editor de código

ui.editor(
"counter.py", # id del buffer
codigo, # texto inicial
path="counter.py", # deduce el lenguaje
markers={6: "modified", 7: "created", 10: "created"},
on_change=self.cambiado, # recibe el texto completo
on_cursor=self.cursor, # recibe (línea, columna), desde 1
)
  • No controlado. El texto, el cursor, la selección y el historial de deshacer viven en Rust, asociados al id. text solo se usa la primera vez que aparece ese id. Para reemplazar el contenido devuelve Command.set_editor_text(id, texto).
  • Un buffer por archivo. Usa la ruta como id: al cambiar de pestaña cada archivo conserva su cursor y su historial.
  • Resaltado. Más de 100 lenguajes (gramáticas de syntect / two-face) con los colores de sintaxis del tema. El lenguaje se deduce de path o se pasa con language="rs".
  • Marcadores de git. markers asigna a cada línea "created", "modified" o "deleted".
  • Cursor. Command.set_editor_cursor(id, línea, columna) mueve el cursor, incluso antes del primer dibujado.
def guardar(self):
Path(self.activa).write_text(self.textos[self.activa])
self.sucios.discard(self.activa)
def cambiado(self, texto):
self.textos[self.activa] = texto
self.sucios.add(self.activa)
  • Líneas largas. Con wrap=False (por defecto) el editor se desplaza en horizontal y los números de línea quedan fijos a la izquierda. Con wrap=True las líneas se ajustan y el número aparece en la primera fila de cada línea.
  • Línea activa. La línea del cursor se resalta y el scroll sigue al cursor (también con RePág/AvPág).

Bloques plegados, code lens y el minimapa

ui.editor(
"app.py", codigo, path="app.py",
minimap=True, # o un ancho en píxeles
cursor_shape="block", # "bar" (por defecto), "block", "underline", "hollow"
on_zoom=self.zoom, # 1, -1 o 0 con Ctrl+= / Ctrl+- / Ctrl+0 y Ctrl+rueda
font_size=self.tamano,
)
def zoom(self, paso):
self.tamano = 14 if paso == 0 else self.tamano + paso
  • Cierre automático (auto_close=True, por defecto). Al escribir (, [, {, ", ' o ` también se inserta el de cierre y el cursor queda en medio. Con una selección, el par la envuelve. Escribir un cierre que ya está a continuación lo salta, Retroceso dentro de un par vacío borra los dos y Enter entre llaves abre una línea con sangría. Las comillas no se cierran dentro de palabras (don't), pero sí tras un prefijo de cadena (f", rb').
  • Plegado (folding=True, por defecto). Los bloques se pliegan según la sangría: pasa el ratón por el margen para ver las flechas y haz clic en una para plegar su bloque. Una línea plegada termina en ⋯ (haz clic para desplegarla). Ctrl+Shift+[ pliega el bloque más interno alrededor del cursor y Ctrl+Shift+] lo despliega. Command.fold_line(id, línea) y Command.fold_all(id) lo hacen desde código. Los números de línea, markers, annotations, on_change, on_cursor y set_editor_cursor siguen usando las líneas reales; editar una línea plegada o mover el cursor dentro de un pliegue lo despliega.
  • Minimapa. minimap=True dibuja el código en miniatura a la derecha con el área visible resaltada; haz clic para saltar, arrastra para desplazarte o usa la rueda encima.
  • Zoom de fuente. El editor pasa Ctrl+=, Ctrl+-, Ctrl+0 y Ctrl+rueda a on_zoom; cambia font_size en respuesta.
  • Cursor. cursor_shape, cursor_blink, cursor_width (de la barra) y cursor_color (por defecto, el color de jugador del tema), como la opción cursor_shape de Zed.

Tres cursores y los resultados de buscar prices

El editor usa los atajos por defecto de Zed y VS Code (Linux y Windows; en macOS, Cmd en lugar de Ctrl):

Teclas Acción
Alt+clic Añade un cursor (o quita el que hay bajo el clic)
Ctrl+Alt+↑ / ↓ Añade un cursor arriba / abajo
Ctrl+D Selecciona la palabra bajo el cursor y luego añade la siguiente coincidencia como cursor
Ctrl+Shift+L Selecciona todas las coincidencias
Alt+Shift+I Un cursor en cada línea de la selección
Ctrl+U Deshace el último cambio de cursores
Esc Vuelve a un cursor y luego quita la selección
Ctrl+Z, Ctrl+Y o Ctrl+Shift+Z Deshacer y rehacer (lo escrito seguido es un solo paso)
Alt+↑ / ↓ Sube / baja las líneas
Alt+Shift+↑ / ↓ o Ctrl+Alt+Shift+↑ / ↓ Duplica las líneas de cada cursor arriba / abajo
Ctrl+Shift+D Duplica la selección de cada cursor justo después (la línea si no hay)
Ctrl+Shift+K Borra las líneas
Ctrl+L Selecciona la línea (otra vez: también la siguiente)
Ctrl+Shift+J Une líneas
Ctrl+Enter / Ctrl+Shift+Enter Nueva línea debajo / encima, con sangría
Ctrl+] / Ctrl+[, Shift+Tab Sangra / quita sangría (Tab sangra una selección de varias líneas)
Ctrl+/ Comenta o descomenta las líneas (#, // o --, según language)
Ctrl+M Salta al corchete pareja (o al que lo encierra)
Ctrl+Retroceso / Ctrl+Supr Borra la palabra anterior / siguiente
Inicio Primer carácter que no es espacio y luego el principio de la línea
Ctrl+↑ / ↓ Desplaza una línea sin mover el cursor
Ctrl+C / Ctrl+X Sin selección, copia / corta la línea entera; con varios cursores, el texto de todos
Ctrl+K Ctrl+0 / Ctrl+J / Ctrl+L Pliega todo / despliega todo / pliega o despliega en el cursor

Escribir, borrar y moverse se aplica a todos los cursores. Al pegar un texto con una línea por cursor, cada cursor recibe su línea, como en Zed. El corchete junto al cursor y su pareja se remarcan (match_brackets), y al seleccionar un texto se resaltan sus demás apariciones (selection_highlight).

Cada acción tiene un nombre (el de Zed, en snake case). on_action(nombre) se llama después de cada una, Command.editor_action(id, nombre) ejecuta una desde código (un menú, una paleta de comandos) y Command.editor_actions() las lista:

ui.editor("main.py", code, path="main.py", on_action=self.ran,
highlights=self.found) # [(línea, columna, línea_final, columna_final)], desde 1
def comment(self):
return pz.Command.editor_action("main.py", "toggle_comments")
def select_matches(self):
# Un cursor por rango; el primero es el cursor principal.
return pz.Command.select_editor_ranges("main.py", self.found)
def replace_all(self):
# Un solo paso de deshacer; on_change recibe el texto nuevo.
return pz.Command.replace_editor_ranges("main.py", [(r, "total") for r in self.found])

Entre los nombres están undo, redo, add_selection_above, add_selection_below, select_next, select_previous, select_all_matches, split_selection_into_lines, undo_selection, cancel, move_line_up, move_line_down, duplicate_line_up, duplicate_line_down, delete_line, newline_above, newline_below, indent, outdent, select_line, join_lines, toggle_comments, move_to_enclosing_bracket, convert_to_upper_case, convert_to_lower_case y sort_lines_case_sensitive.

El chino, el japonés, el coreano y otros idiomas que se escriben con un método de entrada (IME) funcionan en el editor. Mientras compones, el texto del IME se dibuja en un recuadro en el cursor y el cursor se oculta; el texto confirmado se inserta en cada cursor y varias confirmaciones seguidas se deshacen en un solo paso, como al escribir. El IME sigue al cursor cuando lo mueves.

Componiendo 你好 con un método de entrada pinyin

Terminal

salida = "$ pytest -q\n\x1b[32m24 passed\x1b[0m in 1.21s\n$ "
ui.terminal(salida, id="term")

Es una vista de solo lectura que entiende los colores ANSI y se mantiene desplazada al final. Pásale la salida de un proceso que ejecutes tú (por ejemplo con subprocess en un hilo y pz.post). También acepta una lista de líneas de segmentos (texto, color), donde el color es un nombre ANSI ("green", "red", "dim"…) o un token del tema.

ui.ansi(texto) hace la conversión a segmentos por si quieres dibujarlos a tu manera.

Referencia completa: Código.