Projeto
Terminal Engine
Uma console engine. Escreva para o terminal, rode no browser também.
Um terminal virtual construído em volta de uma classe, a BasicConsole. Output, eventos de input, controle de cursor, limpar a tela e medir colunas ficam atrás da API dela. O app se liga uma vez; trocar os hooks do host leva ele do terminal do Node para o xterm.js no browser, ou para os testes, sem reescrever o código de render. Dois apps rodam nela hoje: Console Adventure e RTSim.
Demos públicas · sem conta
Dois programas, uma interface de console
Console Adventure
RPG de fantasia no terminal: explore as Terras Mágicas, enfrente inimigos, ache equipamento. Orientado a objetos, só Node.
RTSim
Simulador de escalonamento preemptivo em tempo discreto para uma ou mais CPUs: EDF, FCFS, HRRN, Priority, Round Robin, SJF e PriorityRR, desenhado a até 60 fps.
Por que separar o console do host
Os dois apps foram escritos para o terminal do Node, e cada um desenhava as telas com os próprios helpers de console. O README do RTSim já dizia que o pequeno motor de render dele precisava ser desacoplado.
Tirar essa camada para uma engine só, com o host plugado por baixo, é o que deixa o mesmo código de render rodar num terminal de verdade e no browser, e dá ao próximo app de console um ponto de partida.
O que os adapters permitem
Renderiza uma vez, qualquer host
O código de render pede a um objeto só para escrever, limpar, mostrar o cursor ou medir a tela. Ele nunca sabe se é Node, xterm.js ou um teste.
Layout que entende cor
Centralizar, quebrar, cortar e fatiar texto com segurança mesmo com códigos de cor ANSI, então um quadro colorido continua alinhado.
Teclas em que o app confia
Eventos de tecla do browser viram strings estáveis como enter, space, esc e as setas antes de chegar no app.
Redimensiona e redesenha
Primeiro o terminal do host se ajusta, depois o app redesenha no tamanho novo. O console continua sendo a única fonte de largura e altura.
Onde fica o limite do host
O código de render nunca sabe o host
A única dependência de uma tela é a classe de console. Node, xterm.js e os testes fornecem cada um um adapter para os mesmos métodos. O custo é um adapter por host, e uma API pequena dentro da qual todo app tem que ficar.
O input é normalizado na borda
O input fica ao lado da classe de console, não dentro dela. O host do browser transforma eventos de tecla em strings estáveis de nível de app, com os modificadores ao lado quando precisa, então a lógica do jogo e do simulador nunca lida com evento do DOM.
Build determinístico em vez de submódulo ao vivo
A produção não busca submódulos, não segue branch flutuante e não depende do checkout git do host. Ela compila a partir de snapshots commitados de cada app. O custo: os snapshots são atualizados na mão.
Apps, console e adapters
- O site é um host React + Vite para o lado xterm.js da engine:
/lista os apps,/console-adventuree/rtsimrodam eles. - Cada app mantém o próprio repositório, fixado no catálogo como submódulo git.
- A produção compila a partir de snapshots do código commitados, então o Stackport nunca precisa de clone recursivo.
Contexto do projeto
- Time
- Sozinho, do design ao deploy
- Período
- 2024-09 – atual
- Status
- No ar em terminal.mattediworks.com
- Stack
- JavaScript, Node.js, React, xterm.js
O que ainda está acoplado
- A engine mora dentro do código dos apps; ainda não é um pacote extraído.
- Os snapshots de código da produção são atualizados na mão.
- O repositório precisa de uma revisão: a branch padrão está atrás da branch de produção.