# ncurses 6.5 — VARIANTE con la BASE DE DATOS terminfo: `/usr/share/terminfo` (~2900 entradas). # NO sustituye a `recipes/ncurses.toml` ni a `recipes/ncurses-tools.toml`. # # ── POR QUÉ EXISTE: la premisa de los fallbacks era una ETIQUETA, no un hecho ──────────────────── # `ncurses-tools.toml` dice, en su propia cabecera, que omitir `install.data` es deliberado porque # los nueve `--with-fallbacks` COMPILADOS dentro de la librería —linux, vt100, vt220, xterm, # xterm-256color, screen, tmux, tmux-256color, ansi— cubren «la consola del metal, QEMU y cualquier # ssh desde un emulador moderno». La decisión era razonable; **la premisa es falsa, y está medida** # (anfitrión `takana`, 2026-09-23, antes de este cambio): # # $ TERM=xterm-256color zsh -f -c 'zmodload zsh/terminfo; echo ${#terminfo}' # 0 # # Cero capacidades para `xterm-256color`, que es UNO DE LOS NUEVE PINEADOS. O sea: el fallback # compilado NO llega. `strings /bin/zsh | grep -c '^xterm-256color$'` ⇒ **0**; la tabla de # fallbacks no viaja dentro del zsh estático. **La causa exacta NO está determinada** y conviene # decirlo así en vez de inventarla: lo medido es que la base no está y el fallback no suple. # # ── LO QUE ROMPÍA, QUE NO SE PARECE A «falta terminfo» ────────────────────────────────────────── # El síntoma no se lee como un problema de base de datos: se lee como una fuente rota y un teclado # roto. Reproducido byte a byte en un pty real contra el zsh del anfitrión: # # · BACKSPACE. Sin `cub1`, zle no sabe mover el cursor a la izquierda. Al borrar emitía un # ESPACIO SUELTO en vez de `\b \b`, así que el carácter no se borraba y el hueco se corría a # la derecha: # # hoy echo hola + ' ' ⇒ un espacio que avanza, no borra # con base echo hola + \b \b ⇒ borra # # · EL PROMPT. Un `?` espurio pegado delante de cada glifo del tema (el `➜` de robbyrussell): # # hoy \x1b[01;32m ? \xe2\x9e\x9c ⇒ se ve ?➜ # con base \x1b[01;32m \xe2\x9e\x9c ⇒ se ve ➜ # # · Flechas, Home y TAB inertes: sin `kcuu1`/`khome` zle no tiene qué bindear. # # ⚠ **El CONTROL importa acá**, porque las dos causas plausibles se prueban a la vez y es fácil # acreditarle el arreglo a la equivocada (el anfitrión es musl y `LANG` viene VACÍO, así que «es el # locale» es la respuesta que uno quiere dar): # # sólo LANG=C.UTF-8 ⇒ SIGUE ROTO: backspace ' ', prompt ?➜ # sólo la base terminfo ⇒ ARREGLADO: backspace \b \b, prompt ➜ ← es esto, y sólo esto # # Y el locale no era sospechoso sin motivo: musl contesta `CODESET=UTF-8` y `MULTIBYTE=on` aun con # `LANG` vacío, o sea que esa pista estaba bien desde el principio. # # ── POR QUÉ UNA RECETA NUEVA Y NO UN PARCHE A LA CANÓNICA ─────────────────────────────────────── # `ncurses.toml` tiene **18 dependientes**: moverle el `install` los re-hashea a todos y a su # cascada, para agregar unos megas de datos que la mayoría no mira. Va como variante, que es el # patrón que el repo ya usa para esto mismo — `ncurses-tools` sobre `ncurses`, `xz-tools` sobre # `xz`, `zstd-cli` sobre `zstd`. Esta receta no re-hashea NADA. # # ── EL PESO, QUE ES EL ARGUMENTO HONESTO EN CONTRA ────────────────────────────────────────────── # Son ~7,5 M y ~2900 entradas, de las que cualquier máquina usa tres. Es mucho para lo que se usa, y # por eso la decisión original de omitirlo no era un descuido. Pero el recorte correcto es elegir # QUÉ entradas viajan (un `--with-fallbacks` que de verdad llegue, o instalar un subconjunto), no # quedarse sin ninguna: **sin base, una terminal interactiva no funciona**, y falla de una forma # que nadie asocia con ncurses. Recortar el set es su propia unidad de trabajo. # ── ⚠ PUNTO DE PARTIDA, NO SELLADA ──────────────────────────────────────────────── # Escrita en el hub el 2026-09-23 y **NO CONSTRUIDA**: en este árbol `takana hash` muere con # `io: No such file or directory (os error 2)` para CUALQUIER receta, incluidas las ya selladas # (`zlib`, `bzip2`, `xz`, `ncurses-tools`), con y sin `TAKANA_LAB=/work/dev-fs`. O sea que el fallo # es del entorno de build del hub, no de esta receta — pero tampoco se pudo descartar por medición. # El primer build va en el worker, y las trampas que ya se conocen están anotadas arriba. # # Mientras tanto el anfitrión lleva la base COPIADA A MANO en `/usr/share/terminfo` (7,5 M, 2899 # entradas, del rootfs Arch de la jaula). Eso está FUERA DEL STORE: se pierde si la imagen se # rehace, y nada va a fallar cuando se pierda — simplemente el backspace vuelve a romperse. Esta # receta existe para que ese parche deje de hacer falta. name = "ncurses-terminfo" version = "6.5" license = "MIT" [source] tarball = "https://ftp.gnu.org/gnu/ncurses/ncurses-6.5.tar.gz" sha256 = "136d91bc269a9a5785e5f9e980bc76ab57428f604ce3e5a5a90cebc767971cc6" [build] compiler = "zig-cc" target = "x86_64-linux-musl" link = "static" # El artefacto son DATOS: no hay ELF que partir. Se deja en `true` igual que las hermanas porque # `strip_debug` entra en `hash_inputs` y divergir acá sólo agrega una diferencia sin motivo. strip_debug = true [deps] build = ["binutils"] [build.phases] # `configure` IDÉNTICO al de la canónica y al de `ncurses-tools`. No hace falta para los datos, pero # `install.data` corre el `tic` que este mismo árbol compila, y ese `tic` tiene que hablar la misma # librería que el resto: una perilla distinta acá haría una base compilada por un `tic` que no es el # que viaja en `ncurses-tools`. configure = "./configure --prefix=/usr --without-shared --with-normal --enable-widec --without-debug --without-ada --without-tests --enable-pc-files --with-pkg-config-libdir=/usr/lib/pkgconfig --with-fallbacks=linux,vt100,vt220,xterm,xterm-256color,screen,tmux,tmux-256color,ansi" compile = "make" # `install.data` es el target que compila `misc/terminfo.src` con `tic` y lo deja en # `/usr/share/terminfo`, más `/usr/share/tabset`. Es lo ÚNICO que se pide: las librerías las da la # canónica y los binarios `ncurses-tools`; duplicarlos acá sería pisar a dos recetas selladas. install = ''' _abuild_phase() { set -e make install.data DESTDIR=/out # GUARDIÁN — regla 3 de CLAUDE.md, y acá es EL riesgo real de esta receta: `install.data` no # compila código, ejecuta el `tic` recién construido sobre `terminfo.src`. Si ese `tic` no # arranca (estático a medias, o sin la librería que espera), el target puede «terminar bien» # y dejar el árbol de directorios CREADO y VACÍO. Y las fases corren con `/bin/sh -c` SIN # `-e` desde el harness, así que un fallo a mitad no aborta: sólo cuenta el último comando. # Un artefacto vacío no falla — llega hasta el final diciendo que todo fue bien y envenena # la caché. Se pregunta por el CONTENIDO, no por el directorio. n=$(find /out/usr/share/terminfo -type f 2>/dev/null | wc -l) if [ "$n" -lt 1000 ]; then echo "ncurses-terminfo: la base salió con $n entradas (se esperan ~2900) — ¿corrió tic? Mirar si install.data falló en silencio: el harness no usa 'sh -e'" exit 1 fi # Y que estén las que de verdad se usan. Una base de 2900 entradas a la que le falte # `xterm-256color` es el mismo fallo con mejor disfraz: hay bulto, no hay servicio. for t in x/xterm-256color x/xterm l/linux s/screen t/tmux-256color; do if [ ! -f "/out/usr/share/terminfo/$t" ]; then echo "ncurses-terminfo: falta la entrada $t en la base — la mayoría de las terminales reales pasan por ahí" exit 1 fi done echo "ncurses-terminfo: $n entradas, con xterm-256color/xterm/linux/screen/tmux-256color presentes" } _abuild_phase '''