pantalla 0.3.0__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 (86) hide show
  1. pantalla-0.3.0/CHANGELOG.md +32 -0
  2. pantalla-0.3.0/LICENSE +21 -0
  3. pantalla-0.3.0/MANIFEST.in +6 -0
  4. pantalla-0.3.0/PKG-INFO +479 -0
  5. pantalla-0.3.0/PUBLICAR.md +116 -0
  6. pantalla-0.3.0/README.md +457 -0
  7. pantalla-0.3.0/docs/fuentes.js +2 -0
  8. pantalla-0.3.0/docs/index.html +5794 -0
  9. pantalla-0.3.0/ejemplos/01_hola.py +13 -0
  10. pantalla-0.3.0/ejemplos/02_cajas_y_colores.py +23 -0
  11. pantalla-0.3.0/ejemplos/03_menu.py +39 -0
  12. pantalla-0.3.0/ejemplos/04_mover.py +26 -0
  13. pantalla-0.3.0/ejemplos/05_serpiente.py +78 -0
  14. pantalla-0.3.0/ejemplos/06_notas_con_print.py +23 -0
  15. pantalla-0.3.0/ejemplos/07_matrices.py +29 -0
  16. pantalla-0.3.0/ejemplos/08_diseno.py +34 -0
  17. pantalla-0.3.0/ejemplos/09_raton.py +175 -0
  18. pantalla-0.3.0/ejemplos/10_space_invaders.py +99 -0
  19. pantalla-0.3.0/ejemplos/11_spinners.py +59 -0
  20. pantalla-0.3.0/ejemplos/12_pelota.py +20 -0
  21. pantalla-0.3.0/pyproject.toml +38 -0
  22. pantalla-0.3.0/setup.cfg +4 -0
  23. pantalla-0.3.0/src/pantalla/__init__.py +219 -0
  24. pantalla-0.3.0/src/pantalla/__main__.py +253 -0
  25. pantalla-0.3.0/src/pantalla/_figlet.py +269 -0
  26. pantalla-0.3.0/src/pantalla/arte.py +122 -0
  27. pantalla-0.3.0/src/pantalla/colores.py +198 -0
  28. pantalla-0.3.0/src/pantalla/componentes.py +552 -0
  29. pantalla-0.3.0/src/pantalla/dibujo.py +169 -0
  30. pantalla-0.3.0/src/pantalla/disenos.py +101 -0
  31. pantalla-0.3.0/src/pantalla/fuentes/3-d.flf +819 -0
  32. pantalla-0.3.0/src/pantalla/fuentes/ansi_regular.flf +723 -0
  33. pantalla-0.3.0/src/pantalla/fuentes/ansi_shadow.flf +723 -0
  34. pantalla-0.3.0/src/pantalla/fuentes/banner3.flf +719 -0
  35. pantalla-0.3.0/src/pantalla/fuentes/big.flf +972 -0
  36. pantalla-0.3.0/src/pantalla/fuentes/big_money-ne.flf +1149 -0
  37. pantalla-0.3.0/src/pantalla/fuentes/block.flf +972 -0
  38. pantalla-0.3.0/src/pantalla/fuentes/bloody.flf +1025 -0
  39. pantalla-0.3.0/src/pantalla/fuentes/calvin_s.flf +315 -0
  40. pantalla-0.3.0/src/pantalla/fuentes/colossal.flf +1137 -0
  41. pantalla-0.3.0/src/pantalla/fuentes/cyberlarge.flf +430 -0
  42. pantalla-0.3.0/src/pantalla/fuentes/delta_corps_priest_1.flf +923 -0
  43. pantalla-0.3.0/src/pantalla/fuentes/doom.flf +834 -0
  44. pantalla-0.3.0/src/pantalla/fuentes/dos_rebel.flf +1138 -0
  45. pantalla-0.3.0/src/pantalla/fuentes/electronic.flf +1233 -0
  46. pantalla-0.3.0/src/pantalla/fuentes/epic.flf +936 -0
  47. pantalla-0.3.0/src/pantalla/fuentes/graffiti.flf +618 -0
  48. pantalla-0.3.0/src/pantalla/fuentes/isometric1.flf +1147 -0
  49. pantalla-0.3.0/src/pantalla/fuentes/larry3d.flf +925 -0
  50. pantalla-0.3.0/src/pantalla/fuentes/mini.flf +500 -0
  51. pantalla-0.3.0/src/pantalla/fuentes/ogre.flf +627 -0
  52. pantalla-0.3.0/src/pantalla/fuentes/puffy.flf +821 -0
  53. pantalla-0.3.0/src/pantalla/fuentes/rectangles.flf +615 -0
  54. pantalla-0.3.0/src/pantalla/fuentes/script.flf +854 -0
  55. pantalla-0.3.0/src/pantalla/fuentes/shadow.flf +622 -0
  56. pantalla-0.3.0/src/pantalla/fuentes/slant.flf +736 -0
  57. pantalla-0.3.0/src/pantalla/fuentes/small.flf +618 -0
  58. pantalla-0.3.0/src/pantalla/fuentes/smslant.flf +649 -0
  59. pantalla-0.3.0/src/pantalla/fuentes/speed.flf +742 -0
  60. pantalla-0.3.0/src/pantalla/fuentes/standard.flf +739 -0
  61. pantalla-0.3.0/src/pantalla/fuentes/starwars.flf +720 -0
  62. pantalla-0.3.0/src/pantalla/fuentes/sub-zero.flf +630 -0
  63. pantalla-0.3.0/src/pantalla/herramientas.py +133 -0
  64. pantalla-0.3.0/src/pantalla/juego.py +1033 -0
  65. pantalla-0.3.0/src/pantalla/letras.py +157 -0
  66. pantalla-0.3.0/src/pantalla/matrices.py +291 -0
  67. pantalla-0.3.0/src/pantalla/raton.py +795 -0
  68. pantalla-0.3.0/src/pantalla/spinners.py +344 -0
  69. pantalla-0.3.0/src/pantalla/teclado.py +478 -0
  70. pantalla-0.3.0/src/pantalla/terminal.py +340 -0
  71. pantalla-0.3.0/src/pantalla/texto.py +134 -0
  72. pantalla-0.3.0/src/pantalla.egg-info/PKG-INFO +479 -0
  73. pantalla-0.3.0/src/pantalla.egg-info/SOURCES.txt +84 -0
  74. pantalla-0.3.0/src/pantalla.egg-info/dependency_links.txt +1 -0
  75. pantalla-0.3.0/src/pantalla.egg-info/entry_points.txt +2 -0
  76. pantalla-0.3.0/src/pantalla.egg-info/top_level.txt +1 -0
  77. pantalla-0.3.0/tests/e2e/demo_raton_windows.py +184 -0
  78. pantalla-0.3.0/tests/e2e/escenario_raton.py +110 -0
  79. pantalla-0.3.0/tests/e2e/raton_linux.py +216 -0
  80. pantalla-0.3.0/tests/e2e/raton_windows.py +261 -0
  81. pantalla-0.3.0/tests/test_juego.py +697 -0
  82. pantalla-0.3.0/tests/test_novatos.py +182 -0
  83. pantalla-0.3.0/tests/test_pantalla.py +725 -0
  84. pantalla-0.3.0/tests/test_raton.py +731 -0
  85. pantalla-0.3.0/tests/test_spinner.py +197 -0
  86. pantalla-0.3.0/tests/test_todo.py +144 -0
@@ -0,0 +1,32 @@
1
+ # Cambios
2
+
3
+ ## 0.3.0
4
+
5
+ - Letras ASCII: `grande()` y `texto_grande()` con `fuente=` (32 fuentes FIGlet). `lista_fuentes()` dice cuáles hay.
6
+ - `arte()` para dibujar arte ASCII con un color por letra.
7
+ - Ratón: `activar_raton()`, `esperar_clic()`, `leer_raton()`, `posicion_raton()`, `zona()`, `boton()`, `botones()` y `bucle()`. Con `arrastrar=True` se puede pintar como con un lápiz.
8
+ - Spinners: `spinner()` y `lista_spinners()`, con `bien()`, `mal()`, `aviso()` e `info()` al acabar.
9
+ - Juegos sin bucles: `jugar()`, `Sprite` (con `capa=`), `sprites()`, `cada()`, `fotograma()` y `pulsada()`.
10
+ - `menu()`: la línea de ayuda se puede mover con `ayuda_x`, `ayuda_y` y `color_ayuda`.
11
+ - `diseno()` entiende el arte y las fuentes del constructor web.
12
+ - Para los que empiezan:
13
+ - en IDLE (Windows) el programa se abre solo en una ventana de cmd;
14
+ - los nombres valen con tildes y ñ (`tamaño()`, `diseño()`);
15
+ - si escribes mal una función te dice cuál querías;
16
+ - las teclas se comparan sin mirar mayúsculas (`tecla == "Intro"`);
17
+ - si se te olvida `global` en un juego te dice qué poner.
18
+ - Arreglado: escribir desde dos hilos a la vez mezclaba letras.
19
+ - Arreglado: con la salida mandada a un archivo en Windows, `caja()` daba error.
20
+ - Probado en Python 3.8, 3.11, 3.13 y 3.14, en Windows y en Linux.
21
+ - Las fuentes vienen de pyfiglet y los spinners de cli-spinners (los créditos están en el README).
22
+
23
+ ## 0.2.0
24
+
25
+ - `menu()` con `ayudas`, `iconos`, secciones (con un diccionario) y scroll.
26
+ - Nuevas: `elegir()`, `calculando()`, `cabecera()`, `pie()`, `matriz()`, `pedir_matriz()`, `regla()`, `depurar()`, `diseno()` y `ayuda()`.
27
+ - Constructor web en `docs/index.html`.
28
+ - Arreglado: al escribir muy rápido en un menú se perdían teclas.
29
+
30
+ ## 0.1.0
31
+
32
+ - Primera versión.
pantalla-0.3.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 phernandez102
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,6 @@
1
+ include LICENSE README.md PUBLICAR.md
2
+ recursive-include ejemplos *.py
3
+ recursive-include tests *.py
4
+ include CHANGELOG.md
5
+ recursive-include docs *.html *.js
6
+ recursive-include src/pantalla/fuentes *.flf
@@ -0,0 +1,479 @@
1
+ Metadata-Version: 2.4
2
+ Name: pantalla
3
+ Version: 0.3.0
4
+ Summary: gotoxy para el siglo XXI: colores, cajas, menús, letras ASCII, ratón, spinners y juegos sin bucles en la terminal. En español y pensada para aprender Python.
5
+ Author: phernandez102
6
+ License-Expression: MIT
7
+ Project-URL: Constructor web, https://phernandez102.github.io/pantalla/
8
+ Project-URL: Código, https://github.com/phernandez102/pantalla
9
+ Keywords: terminal,consola,gotoxy,colores,tui,menu,educación,español,conio,ascii-art,figlet,juegos,spinner,raton,principiantes
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Education
13
+ Classifier: Natural Language :: Spanish
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Topic :: Education
17
+ Classifier: Topic :: Terminals
18
+ Requires-Python: >=3.8
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Dynamic: license-file
22
+
23
+ # pantalla
24
+
25
+ > **gotoxy para el siglo XXI.**
26
+
27
+ **pantalla** convierte la terminal en un lienzo para aprender Python. Con una línea pones texto donde quieras y con colores, dibujas cajas y menús, escribes títulos con 32 fuentes ASCII o conviertes una imagen en arte de caracteres. Tiene botones que responden al ratón, spinners para tareas largas y un modo juego: escribes qué pasa en cada momento y la librería se encarga del resto, sin parpadeos y sin bucles infinitos. Todo en español.
28
+
29
+ ```python
30
+ import pantalla
31
+
32
+ pantalla.limpiar()
33
+ pantalla.rodear("=")
34
+ pantalla.centrar("¡Hola, mundo!", color="amarillo", negrita=True)
35
+ pantalla.gotoxy(3, 2)
36
+ print("Esto está en la columna 3, fila 2")
37
+ pantalla.esperar()
38
+ ```
39
+
40
+ - No necesita instalar nada más (solo Python 3.8 o más nuevo).
41
+ - Funciona en Windows, Linux y Mac.
42
+ - Se mezcla sin problemas con `print()` e `input()`.
43
+ - Si te equivocas, los errores te dicen qué ha pasado en español: `No conozco el color 'rojoo'. ¿Querías decir 'rojo'?`
44
+ - Tiene un **constructor web**: dibujas la pantalla con el ratón, copias el código y lo pegas en tu programa.
45
+
46
+ ## Instalar
47
+
48
+ ```
49
+ pip install pantalla
50
+ ```
51
+
52
+ Para ver todo lo que hace, abre una demostración:
53
+
54
+ ```
55
+ python -m pantalla
56
+ ```
57
+
58
+ Y desde Python, `pantalla.ayuda()` abre un menú con todas las funciones: eliges una con las flechas y te enseña cómo se usa. `pantalla.ayuda("caja")` te lo dice directamente de una.
59
+
60
+ ## Dónde funciona
61
+
62
+ En cualquier terminal de verdad: **cmd**, **PowerShell**, **Windows Terminal**, la terminal de **VS Code**, la de Linux o la de Mac.
63
+
64
+ **IDLE** no es una terminal. En Windows, si pulsas F5 en IDLE, pantalla abre tu programa en una ventana de cmd y lo ejecuta allí (si no quieres que lo haga, pon la variable de entorno `PANTALLA_NO_ABRIR=1`). En Linux y Mac, ejecútalo desde la terminal. En **Thonny**, usa *Ejecutar → Ejecutar el script actual en terminal*.
65
+
66
+ ## Si algo falla
67
+
68
+ Los errores te dicen en español qué ha pasado y cómo arreglarlo:
69
+
70
+ ```
71
+ >>> pantalla.escribe("hola")
72
+ AttributeError: pantalla no tiene ninguna función que se llame 'escribe'. ¿Querías decir pantalla.escribir...?
73
+
74
+ >>> pantalla.escribir(5, 3, "hola")
75
+ TypeError: escribir: 'y' tiene que ser un número, pero me has dado 'hola'. ¿Has puesto el texto al final? ...
76
+
77
+ >>> pantalla.gotoxy("5", 3)
78
+ TypeError: gotoxy: 'x' tiene que ser un número, pero me has dado '5'. Es un número entre comillas...
79
+ ```
80
+
81
+ - Puedes escribir los nombres con tildes y ñ: `pantalla.tamaño()`, `pantalla.diseño()`, `pantalla.pedir_contraseña()`.
82
+ - Al comparar teclas no importan las mayúsculas ni el nombre: `tecla == "Intro"`, `tecla == "ENTER"` y `tecla == "enter"` valen igual, y `tecla == " "` es el espacio.
83
+ - Si en un juego se te olvida `global`, el error te dice qué línea tienes que poner.
84
+
85
+ ## Cómo funcionan las posiciones
86
+
87
+ La pantalla es una cuadrícula de letras. `x` es la columna (hacia la derecha) e `y` la fila (hacia abajo). **Las dos empiezan en 1**: la esquina de arriba a la izquierda es `(1, 1)`.
88
+
89
+ ```
90
+ (1,1) ──────────── x ───────────▶ (80,1)
91
+ │
92
+ │ pantalla.gotoxy(10, 3)
93
+ y ▼
94
+ │ aquí
95
+ ▼
96
+ (1,24) (80,24)
97
+ ```
98
+
99
+ `pantalla.ancho()` y `pantalla.alto()` te dicen cuánto mide la tuya. Si haces cuentas como `pantalla.ancho() / 2` y te sale un número con decimales, no pasa nada: se redondea solo.
100
+
101
+ **¿No sabes en qué posición está algo?** Escribe en la terminal `python -m pantalla depurar`: sale una cruz que mueves con las flechas y te dice su `x` y su `y` (y el `gotoxy` que tienes que escribir). Dentro de tu programa, `pantalla.regla()` pinta los números de las columnas y las filas en los bordes.
102
+
103
+ ## Todo lo que hay
104
+
105
+ ### Pantalla y cursor
106
+
107
+ | Función | Qué hace |
108
+ |---|---|
109
+ | `limpiar()` | Borra la pantalla |
110
+ | `limpiar_linea(y)` | Borra una línea |
111
+ | `gotoxy(x, y)` | Mueve el cursor (también se llama `ir_a`) |
112
+ | `ancho()`, `alto()`, `tamano()` | Lo que mide la terminal |
113
+ | `centro()` | Devuelve `(x, y)` del centro |
114
+ | `ocultar_cursor()`, `mostrar_cursor()` | Esconde o enseña el cursor |
115
+ | `guardar_posicion()`, `volver_a_posicion()` | Apunta dónde está el cursor y vuelve luego |
116
+ | `titulo_ventana("Mi juego")` | Cambia el título de la ventana |
117
+ | `pitido()` | Bip |
118
+ | `pausa(0.5)` | Espera medio segundo |
119
+ | `iniciar()`, `terminar()` | Prepara la terminal para un juego y la deja como estaba |
120
+ | `regla()` | Pinta los números de columnas y filas, para ver posiciones |
121
+ | `depurar()` | Herramienta para ver posiciones moviendo una cruz con las flechas |
122
+
123
+ ### Escribir
124
+
125
+ ```python
126
+ pantalla.escribir("Hola", 10, 5) # columna 10, fila 5
127
+ pantalla.escribir("Peligro", 10, 6, color="rojo", negrita=True)
128
+ pantalla.escribir("Puntos: 120", 1, 1, color="negro", fondo="amarillo")
129
+ pantalla.escribir("Centrado", "centro", 5) # centrado en la fila 5
130
+ pantalla.centrar("GAME OVER", color="rojo") # en el centro de la pantalla
131
+ pantalla.centrar("Pulsa una tecla", y=20) # centrado en la fila 20
132
+ pantalla.escribir_derecha("Vidas: 3", 1) # pegado a la derecha
133
+ pantalla.escribir_lento("Había una vez...", 5, 3, velocidad=0.08) # letra a letra
134
+ pantalla.grande("HOLA", color="amarillo") # letras gigantes
135
+ print(pantalla.texto_grande("FIN")) # letras gigantes con print
136
+ pantalla.cabecera("MATRICES · Suma") # barra con título arriba
137
+ pantalla.pie("↑↓ moverse Enter elegir Esc salir") # texto en la última fila
138
+ ```
139
+
140
+ Si el texto tiene varias líneas (con `\n`), todas empiezan en la misma columna, así que puedes hacer dibujos:
141
+
142
+ ```python
143
+ pantalla.escribir(" /\\_/\\\n( o.o )\n > ^ <", 30, 10, color="naranja")
144
+ ```
145
+
146
+ Estilos que puedes poner a cualquier texto: `negrita`, `tenue`, `cursiva`, `subrayado`, `parpadeo`, `invertido` y `tachado`.
147
+
148
+ #### Fuentes ASCII art
149
+
150
+ `grande()` y `texto_grande()` tienen `fuente=`, con 32 fuentes FIGlet (las mismas de las webs de "texto a ASCII art"). Sin fuente usa `"bloques"`, la de siempre.
151
+
152
+ ```python
153
+ pantalla.grande("Hola", fuente="slant", color="cian")
154
+ print(pantalla.texto_grande("Hola", fuente="standard"))
155
+ print(pantalla.lista_fuentes()) # ['bloques', '3-d', 'ansi_regular', 'ansi_shadow', ...]
156
+ ```
157
+
158
+ ```
159
+ __ __ __ _ _ _
160
+ / / / /___ / /___ _ | | | | ___ | | __ _
161
+ / /_/ / __ \/ / __ `/ | |_| |/ _ \| |/ _` |
162
+ / __ / /_/ / / /_/ / | _ | (_) | | (_| |
163
+ /_/ /_/\____/_/\__,_/ |_| |_|\___/|_|\__,_|
164
+ fuente="slant" fuente="standard"
165
+
166
+ █████╗ ███╗ ██╗███████╗██╗
167
+ ██╔══██╗████╗ ██║██╔════╝██║
168
+ ███████║██╔██╗ ██║███████╗██║
169
+ ██╔══██║██║╚██╗██║╚════██║██║
170
+ ██║ ██║██║ ╚████║███████║██║
171
+ ╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚═╝
172
+ fuente="ansi_shadow"
173
+ ```
174
+
175
+ El nombre vale en mayúsculas o con espacios (`"ANSI Shadow"`). Si una letra no está en la fuente se usa la misma sin tilde (á → a), y si tampoco está, se salta.
176
+
177
+ ### Colores
178
+
179
+ Los colores se escriben en español, con o sin tildes y mayúsculas:
180
+
181
+ `negro`, `rojo`, `verde`, `amarillo`, `azul`, `morado`, `cian`, `gris claro`, `gris`, `rojo claro`, `verde claro`, `amarillo claro`, `azul claro`, `morado claro`, `cian claro`, `blanco`, `naranja`, `marrón`, `rosa`.
182
+
183
+ También valen en hexadecimal (`"#ff8800"`), en RGB (`(255, 136, 0)`) o con un número del 0 al 255.
184
+
185
+ ```python
186
+ print("Esto es", pantalla.colorear("importante", "rojo", negrita=True))
187
+
188
+ pantalla.poner_color("verde") # a partir de aquí todo sale en verde, también con print
189
+ print("Verde")
190
+ pantalla.quitar_color() # vuelta a lo normal
191
+
192
+ pantalla.poner_color(fondo="azul")
193
+ pantalla.limpiar() # ¡toda la pantalla azul!
194
+ ```
195
+
196
+ ### Dibujar
197
+
198
+ ```python
199
+ pantalla.rodear() # borde alrededor de toda la pantalla
200
+ pantalla.rodear("=") # con =
201
+ pantalla.rodear("*", color="amarillo", titulo="Mi juego")
202
+
203
+ pantalla.caja(5, 3, 30, 10) # x, y, ancho, alto
204
+ pantalla.caja(5, 3, 30, 10, estilo="doble", color="cian", titulo="Inventario")
205
+ pantalla.caja(5, 3, 30, 10, relleno=True) # borra lo que haya dentro
206
+ pantalla.caja(ancho=40, alto=8, titulo="Aviso") # sin x ni y: en el centro
207
+
208
+ pantalla.linea(12) # línea horizontal en la fila 12
209
+ pantalla.linea(12, "-", x=5, largo=20, color="gris")
210
+ pantalla.linea_vertical(40) # línea vertical en la columna 40
211
+ pantalla.rellenar(10, 5, 20, 4, fondo="azul") # un rectángulo de color
212
+ pantalla.rellenar(10, 5, 20, 4) # borra esa zona
213
+ pantalla.punto(10, 5, "@", color="amarillo") # un solo carácter
214
+ ```
215
+
216
+ Estilos de borde: `"simple"` ┌─┐, `"doble"` ╔═╗, `"grueso"` ┏━┓, `"redondo"` ╭─╮, `"ascii"` +-+ o cualquier carácter, como `"="` o `"#"`.
217
+
218
+ #### Arte ASCII (con colores)
219
+
220
+ `arte()` dibuja un dibujo hecho con letras. Los espacios son transparentes (no borran lo de debajo):
221
+
222
+ ```python
223
+ gato = r'''
224
+ /\_/\
225
+ ( o.o )
226
+ > ^ <
227
+ '''
228
+ pantalla.arte(gato, 10, 5, color="amarillo")
229
+ ```
230
+
231
+ Para darle color a cada letra, pásale otro dibujo del mismo tamaño con una letra de color en cada sitio:
232
+
233
+ ```python
234
+ pantalla.arte(["(^_^)", "/| |\\"], 5, 5,
235
+ colores=["aaaaa",
236
+ "vv vv"])
237
+ ```
238
+
239
+ Códigos: `r` rojo, `v` verde, `a` amarillo, `z` azul, `m` morado, `c` cian, `b` blanco, `n` negro, `g` gris, `o` naranja, `x` marrón, `p` rosa; en mayúscula la versión "claro" (`R` rojo claro, `G` gris claro...). Un espacio o un punto deja el color normal. `fondos=` funciona igual para el fondo. Con `transparente=False` los espacios sí borran. Están en `pantalla.CODIGOS_COLOR`.
240
+
241
+ El constructor web convierte imágenes en arte ASCII y te da el código de `arte()` ya hecho.
242
+
243
+ ### Teclado
244
+
245
+ ```python
246
+ t = pantalla.tecla() # espera a que pulses una tecla (sin Enter)
247
+ if t == "arriba":
248
+ ...
249
+
250
+ nombre = pantalla.pedir("¿Cómo te llamas? ") # como input()
251
+ nombre = pantalla.pedir("Nombre: ", 10, 5, color="cian") # en una posición
252
+ edad = pantalla.pedir_numero("Edad: ", minimo=0, maximo=120) # insiste hasta que sea un número
253
+ precio = pantalla.pedir_numero("Precio: ", decimales=True) # vale 2,5 y 2.5
254
+ clave = pantalla.pedir_contrasena() # no se ve lo que escribes
255
+ if pantalla.confirmar("¿Quieres salir? (s/n) "): # True o False
256
+ ...
257
+ pantalla.esperar() # "Pulsa una tecla para continuar..."
258
+ ```
259
+
260
+ `tecla()` devuelve las letras tal cual (`"a"`, `"A"`, `"ñ"`, `"7"`) y estos nombres para las especiales:
261
+
262
+ `"arriba"`, `"abajo"`, `"izquierda"`, `"derecha"`, `"enter"`, `"espacio"`, `"esc"`, `"tab"`, `"borrar"`, `"suprimir"`, `"insertar"`, `"inicio"`, `"fin"`, `"repag"`, `"avpag"`, `"f1"` … `"f12"`, `"ctrl+a"` … y `"alt+x"` …
263
+
264
+ ### Cosas ya hechas
265
+
266
+ ```python
267
+ opcion = pantalla.menu(["Jugar", "Opciones", "Salir"], titulo="Menú") # con flechas y Enter
268
+ if opcion == "Jugar":
269
+ ...
270
+
271
+ pantalla.mensaje("¡Has ganado!", titulo="Enhorabuena", color_borde="verde")
272
+ dificultad = pantalla.elegir("Dificultad:", ["Fácil", "Normal", "Difícil"]) # opciones en fila, con ← →
273
+
274
+ pantalla.tabla([["Ana", 8.5], ["Luis", 6]], cabeceras=["Nombre", "Nota"])
275
+
276
+ for i in range(101):
277
+ pantalla.barra_progreso(i, 100, 10, 5)
278
+ pantalla.pausa(0.02)
279
+
280
+ pantalla.cargando(3, "Guardando partida") # "Cargando..." en la línea donde estés
281
+ pantalla.calculando() # ventanita de "Calculando..." en el centro
282
+ ```
283
+
284
+ #### Spinners (la ruedecita que gira mientras trabajas)
285
+
286
+ Como la librería [halo](https://github.com/manrajgrover/halo): gira sola mientras tu programa sigue.
287
+
288
+ ```python
289
+ with pantalla.spinner("Descargando..."): # al acabar pone ✔ (o ✖ si hay un error)
290
+ descargar_todo()
291
+
292
+ s = pantalla.spinner("Paso 1", estilo="arco", color="amarillo").empezar()
293
+ s.texto = "Paso 2" # cambia el texto mientras gira
294
+ s.bien("Hecho") # ✔ Hecho (también mal(), aviso(), info(), parar())
295
+
296
+ pantalla.spinner("Guardando", x=10, y=5) # en un sitio fijo de la pantalla
297
+ pantalla.lista_spinners() # los ~60 estilos: "dots", "line", "arc", "pelota", "tiburon"...
298
+ ```
299
+
300
+ Sin terminal de verdad (IDLE) no gira: escribe el texto una vez y luego el final.
301
+
302
+ `menu()` devuelve el texto de la opción elegida (o `None` si pulsas Esc). También se puede elegir pulsando el número. Si hay más opciones de las que caben, el menú hace scroll.
303
+
304
+ #### Menús con ayuda, iconos y secciones
305
+
306
+ ```python
307
+ opcion = pantalla.menu(
308
+ ["Jugar", "Opciones", "Salir"],
309
+ ayudas={"Jugar": "Empieza una partida nueva", "Salir": "Cierra el juego"}, # sale debajo
310
+ iconos={"Jugar": "►", "Opciones": "*", "Salir": "×"},
311
+ )
312
+
313
+ # la explicación también puede ir en otro sitio, por ejemplo abajo del todo:
314
+ AYUDA = {"Jugar": "Empieza una partida nueva", "Salir": "Cierra el juego"}
315
+ opcion = pantalla.menu(["Jugar", "Salir"], ayudas=AYUDA,
316
+ ayuda_x=3, ayuda_y=pantalla.alto() - 2, color_ayuda="cian")
317
+ ```
318
+
319
+ Si le das un **diccionario** en vez de una lista, hace un menú con cada sección en su caja y en columnas, como el de un programa de verdad. Te mueves con las cuatro flechas:
320
+
321
+ ```python
322
+ opcion = pantalla.menu({
323
+ "Operaciones": ["Sumar", "Restar", "Multiplicar"],
324
+ "Determinantes": ["Determinante", "Inversa"],
325
+ "Otros": ["Historial", "Ajustes", "Salir"],
326
+ }, ayudas={"Sumar": "Suma dos matrices del mismo tamaño"})
327
+ ```
328
+
329
+ ### Ratón
330
+
331
+ ```python
332
+ pantalla.activar_raton(hover=True) # hover=True: también se entera de cuándo mueves el ratón
333
+
334
+ opcion = pantalla.botones(["Jugar", "Opciones", "Salir"]) # botones que se pulsan con clic (o flechas + Enter)
335
+
336
+ x, y, boton = pantalla.esperar_clic() # espera un clic; boton es "izquierdo", "derecho" o "central"
337
+ clic = pantalla.leer_raton() # como tecla_pulsada(): None si no hay clic
338
+ pos = pantalla.posicion_raton() # (x, y) de dónde está el ratón
339
+
340
+ aceptar = pantalla.boton("Aceptar", 10, 10, al_clic=lambda: "ok") # cambia de color al pasar por encima
341
+ cancelar = pantalla.boton("Cancelar", 22, 10, al_clic=lambda: "no")
342
+ zona = pantalla.zona(5, 3, 20, 4, al_clic=lambda: "zona") # un rectángulo invisible que se puede pulsar
343
+ resultado = pantalla.bucle([aceptar, cancelar, zona]) # espera hasta que algo devuelva un valor (o Esc)
344
+
345
+ pantalla.desactivar_raton()
346
+ ```
347
+
348
+ Funciona en Windows (cmd, PowerShell, Windows Terminal) y en las terminales de Linux y Mac.
349
+
350
+ ### Matrices
351
+
352
+ ```python
353
+ A = pantalla.pedir_matriz("A") # eliges el tamaño con las flechas y rellenas cada hueco
354
+ B = pantalla.pedir_matriz("B", filas=2, columnas=3) # tamaño fijo
355
+ C = pantalla.pedir_matriz("C", cuadrada=True) # filas y columnas suben a la vez
356
+
357
+ pantalla.matriz(A) # la dibuja con corchetes, como un print
358
+ pantalla.matriz(A, 5, 3, nombre="A") # en la columna 5, fila 3, con "A ="
359
+ pantalla.matriz(A, 5, 3, det=True) # con barras, como un determinante
360
+ ```
361
+
362
+ `pedir_matriz()` acepta enteros, decimales (`2.5` o `2,5`) y fracciones (`1/2`). Devuelve una lista de filas, por ejemplo `[[1, 2], [3, 4]]`. Con `fracciones=True` devuelve `Fraction` en vez de decimales.
363
+
364
+ ## Hacer un juego
365
+
366
+ Con `pantalla.jugar()` no hace falta ningún `while`: escribes una función que dibuja **un momento** del juego y `jugar()` la llama 20 veces por segundo (o las que digas con `velocidad=`). Todo lo que dibujas sale de golpe, sin parpadeos, y al acabar la terminal queda como estaba.
367
+
368
+ ```python
369
+ import pantalla
370
+
371
+ nave = pantalla.Sprite("/^\\", 30, 20, color="verde") # un dibujo que se mueve: se pinta solo
372
+
373
+ def actualizar(tecla): # tecla: la que se acaba de pulsar, o None
374
+ if pantalla.pulsada("izquierda"): # True mientras la mantienes pulsada
375
+ nave.mover(-1, 0)
376
+ if pantalla.pulsada("derecha"):
377
+ nave.mover(1, 0)
378
+ if pantalla.cada(1): # True una vez cada segundo
379
+ ...
380
+ pantalla.escribir("Fotograma %d" % pantalla.fotograma(), 1, 1)
381
+ if tecla == "q":
382
+ return "adiós" # devolver algo acaba el juego
383
+
384
+ resultado = pantalla.jugar(actualizar, velocidad=20, ancho=60, alto=22) # Esc también sale
385
+ ```
386
+
387
+ - Dentro de `actualizar` vale **todo** lo de pantalla (`escribir`, `caja`, `grande`, `print`...). Se borra solo antes de cada fotograma.
388
+ - `Sprite(dibujo, x, y, color=, colores=, fotogramas=[...], cada=5, capa=0)`: `mover()`, `choca(otro o lista)`, `fuera()`, `eliminar()`. `pantalla.sprites()` da los que hay.
389
+ - `capa=`: si dos sprites se pisan, se ve el de capa más alta. Con capa negativa el sprite es de fondo (estrellas, hierba...) y queda detrás de lo que dibujes tú.
390
+ - `escribir_lento()` dentro del juego se ve letra a letra (el juego espera mientras escribe, como con `pausa()`).
391
+ - Para guardar cosas que cambian (puntos, vidas...) tienes dos opciones. Una es poner `global puntos` en la primera línea de `actualizar`. La otra es apuntarlas en un sprite: `pelota.dx = 1`, y así no hace falta `global`. Lo puedes ver en `ejemplos/12_pelota.py`.
392
+ - `jugar(..., raton=True)` para usar `leer_raton()` dentro; `fondo="azul"` pinta el fondo.
393
+ - En Linux y Mac, `pulsada()` depende de la repetición del teclado (hay un pequeño retraso al empezar a mantener una tecla). En Windows va perfecta.
394
+
395
+ Mira `ejemplos/10_space_invaders.py` (un Space Invaders en ~90 líneas, doble clic en `jugar_space_invaders.bat` en Windows) y `ejemplos/12_pelota.py` (lo mínimo).
396
+
397
+ Si prefieres hacerlo a mano, `tecla_pulsada()` mira si hay una tecla pulsada **sin esperar**, y si no hay devuelve `None`:
398
+
399
+ ```python
400
+ import pantalla
401
+
402
+ pantalla.iniciar() # pantalla aparte, sin cursor y sin que se vean las teclas
403
+ x = 1
404
+ while x < pantalla.ancho():
405
+ t = pantalla.tecla_pulsada()
406
+ if t == "q":
407
+ break
408
+ pantalla.punto(x, 10, " ")
409
+ x = x + 1
410
+ pantalla.punto(x, 10, "►", color="amarillo")
411
+ pantalla.pausa(0.05)
412
+ pantalla.terminar() # todo como estaba
413
+ ```
414
+
415
+ En la carpeta `ejemplos` hay una **serpiente** completa con poco más de 60 líneas.
416
+
417
+ ## El constructor web
418
+
419
+ Es una página donde dibujas la pantalla con el ratón: cajas, textos, líneas, letras grandes, colores... Mientras pasas el ratón te dice la `x` y la `y` de cada sitio, y abajo te va escribiendo el código.
420
+
421
+ **Ábrelo en: https://phernandez102.github.io/pantalla/**
422
+
423
+ Te da el código de dos formas:
424
+
425
+ 1. **Código Python**: un programa normal con una línea por cada cosa (`pantalla.caja(...)`, `pantalla.escribir(...)`...). Es el mejor para aprender.
426
+ 2. **Para `pantalla.diseno()`**: todo el dibujo en una sola línea. Así lo puedes volver a abrir en el constructor, cambiarlo y pegarlo otra vez.
427
+
428
+ ```python
429
+ import pantalla
430
+
431
+ pantalla.limpiar()
432
+ zonas = pantalla.diseno(r'''{"pantalla": 1, "ancho": 80, "alto": 24, "elementos": [...]}''')
433
+
434
+ x, y = zonas["puntos"] # dónde está el hueco "puntos" que dibujaste
435
+ pantalla.escribir(120, x, y, color="amarillo")
436
+ ```
437
+
438
+ En el constructor puedes ponerle **nombre** a cualquier cosa, y hay una herramienta de **huecos con nombre**: sitios que dejas libres para que tu programa escriba encima (los puntos, el nombre del jugador...). `pantalla.diseno()` te devuelve dónde está cada uno.
439
+
440
+ También vale guardar el diseño en un archivo `mi_pantalla.json` y hacer `pantalla.diseno("mi_pantalla.json")`. Con `centrado=True` se coloca en el centro de la terminal, aunque sea más grande que el diseño.
441
+
442
+ ## Ejemplos
443
+
444
+ En la carpeta `ejemplos` del repositorio hay programas cortos, del más fácil al más difícil:
445
+
446
+ 1. `01_hola.py`: lo mínimo
447
+ 2. `02_cajas_y_colores.py`: cajas, colores y rectángulos
448
+ 3. `03_menu.py`: un programa con menú y varias opciones
449
+ 4. `04_mover.py`: mover una @ con las flechas
450
+ 5. `05_serpiente.py`: el juego de la serpiente
451
+ 6. `06_notas_con_print.py`: mezclar `print` normal con `pedir_numero` y `tabla`
452
+ 7. `07_matrices.py`: pedir dos matrices con las flechas y sumarlas
453
+ 8. `08_diseno.py`: usar una pantalla hecha con el constructor web
454
+ 9. `09_raton.py`: botones y clics con el ratón
455
+ 10. `10_space_invaders.py`: un Space Invaders con `jugar()` y `Sprite`, sin ningún `while`
456
+ 11. `11_spinners.py`: spinners que giran mientras el programa trabaja
457
+ 12. `12_pelota.py`: el juego más pequeño posible, una pelota que rebota
458
+
459
+ ## ¿Cómo funciona por dentro?
460
+
461
+ Con **códigos ANSI**: textos especiales que empiezan por el carácter ESC (`\x1b`) y que la terminal entiende como órdenes en vez de como letras. Por ejemplo:
462
+
463
+ ```python
464
+ print("\x1b[31mHola") # Hola en rojo
465
+ print("\x1b[5;10H*") # un * en la fila 5, columna 10
466
+ ```
467
+
468
+ `pantalla` solo te ahorra tener que acordarte de todos esos códigos. Si tienes curiosidad, el código está escrito para que se entienda: empieza por `terminal.py`.
469
+
470
+ Para leer teclas sueltas usa `msvcrt` en Windows y `termios` en Linux y Mac, que vienen con Python.
471
+
472
+ ## Licencia
473
+
474
+ MIT: puedes usarla, copiarla y cambiarla como quieras.
475
+
476
+ Incluye trabajo de otros, con sus propias licencias:
477
+
478
+ - **Fuentes FIGlet** (`src/pantalla/fuentes/*.flf`): vienen de [pyfiglet](https://github.com/pwaller/pyfiglet) (MIT). Cada fuente es de su autor y conserva su licencia y sus créditos en las primeras líneas del archivo. Solo se han quitado los caracteres que no se usan.
479
+ - **Animaciones de los spinners**: de [cli-spinners](https://github.com/sindresorhus/cli-spinners) (MIT, © Sindre Sorhus).
@@ -0,0 +1,116 @@
1
+ # Cómo publicar `pantalla` en PyPI
2
+
3
+ ## 0. Antes de nada
4
+
5
+ 1. **Mira si el nombre está libre**: abre <https://pypi.org/project/pantalla/>. Si sale "404 Not Found", está libre (lo estaba el 4 de noviembre de 2026). Si sale una página con otro proyecto, está cogido y tendrás que cambiar `name` en `pyproject.toml` (por ejemplo `pantalla-tic` o `pantalla-facil`). El `import pantalla` puede seguir igual.
6
+ 2. El autor (`pyproject.toml` y `LICENSE`) y los enlaces de GitHub (`README.md` y `pyproject.toml`) ya están puestos con el usuario `phernandez102`.
7
+
8
+ ## 1. Crear las cuentas
9
+
10
+ - Cuenta de pruebas: <https://test.pypi.org/account/register/>
11
+ - Cuenta de verdad: <https://pypi.org/account/register/>
12
+
13
+ Son dos cuentas distintas. Las dos te obligan a activar la verificación en dos pasos (con una app como Google Authenticator).
14
+
15
+ En cada una crea un **token** (Account settings → API tokens → Add API token, con alcance "Entire account" la primera vez). Cópialo: empieza por `pypi-` y solo se ve una vez.
16
+
17
+ ## 2. Instalar las herramientas
18
+
19
+ ```
20
+ pip install --upgrade build twine
21
+ ```
22
+
23
+ ## 3. Probar que todo va
24
+
25
+ Desde la carpeta del proyecto:
26
+
27
+ ```
28
+ python -m unittest discover -s tests
29
+ ```
30
+
31
+ Tienen que salir 247 tests y al final `OK`.
32
+
33
+ ## 4. Construir el paquete
34
+
35
+ ```
36
+ python -m build
37
+ ```
38
+
39
+ Esto crea la carpeta `dist/` con dos archivos: `pantalla-0.3.0.tar.gz` y `pantalla-0.3.0-py3-none-any.whl`.
40
+
41
+ Comprueba que están bien:
42
+
43
+ ```
44
+ python -m twine check dist/*
45
+ ```
46
+
47
+ ## 5. Subirlo primero a la web de pruebas
48
+
49
+ ```
50
+ python -m twine upload --repository testpypi dist/*
51
+ ```
52
+
53
+ Cuando pida el usuario escribe `__token__` y como contraseña pega el token de **TestPyPI**.
54
+
55
+ Pruébalo en otro ordenador (o en un entorno virtual):
56
+
57
+ ```
58
+ pip install --index-url https://test.pypi.org/simple/ pantalla
59
+ python -m pantalla
60
+ ```
61
+
62
+ ## 6. Subirlo de verdad
63
+
64
+ ```
65
+ python -m twine upload dist/*
66
+ ```
67
+
68
+ Usuario `__token__` y el token de **PyPI** (el de verdad). A partir de ahí cualquiera puede hacer:
69
+
70
+ ```
71
+ pip install pantalla
72
+ ```
73
+
74
+ ## 7. Sacar una versión nueva
75
+
76
+ 1. Cambia el número de versión en **dos sitios**: `pyproject.toml` (`version = "0.3.1"`) y `src/pantalla/__init__.py` (`__version__ = "0.3.1"`).
77
+ 2. Borra la carpeta `dist/` vieja.
78
+ 3. Repite los pasos 4 y 6.
79
+
80
+ PyPI no deja subir dos veces la misma versión, ni aunque borres la anterior.
81
+
82
+ Para no tener que escribir el token cada vez, puedes guardarlo en un archivo `.pypirc` en tu carpeta de usuario:
83
+
84
+ ```ini
85
+ [pypi]
86
+ username = __token__
87
+ password = pypi-XXXXXXXX
88
+ ```
89
+
90
+ (No subas nunca ese archivo a GitHub.)
91
+
92
+
93
+ # Cómo poner el constructor web en GitHub Pages
94
+
95
+ El constructor son dos archivos: `docs/index.html` y `docs/fuentes.js` (las letras ASCII). Tienen que estar juntos en la misma carpeta. No necesita servidor ni instalar nada.
96
+
97
+ 1. Crea un repositorio en GitHub que se llame `pantalla` (público).
98
+ 2. Sube todos los archivos del proyecto. Lo más fácil sin saber git: en la página del repositorio, *Add file → Upload files* y arrastra todo el contenido de la carpeta (incluida la carpeta `docs`).
99
+ Con git sería:
100
+ ```
101
+ git init
102
+ git add .
103
+ git commit -m "pantalla 0.3.0"
104
+ git branch -M main
105
+ git remote add origin https://github.com/phernandez102/pantalla.git
106
+ git push -u origin main
107
+ ```
108
+ 3. En el repositorio: **Settings → Pages**. En *Build and deployment* elige:
109
+ - Source: **Deploy from a branch**
110
+ - Branch: **main** y la carpeta **/docs**
111
+ - Pulsa **Save**.
112
+ 4. Espera un minuto y entra en `https://phernandez102.github.io/pantalla/`. Ahí está el constructor.
113
+
114
+ Cada vez que cambies `docs/index.html` y lo subas, la web se actualiza sola en un minuto.
115
+
116
+ Lo que dibuja cada persona en el constructor se guarda en su navegador, así que si recarga la página no lo pierde. No se guarda en ningún servidor.