8 pontos por GN⁺ 2026-03-12 | 5 comentários | Compartilhar no WhatsApp
  • Devido às limitações do editor Howl (desenvolvimento descontinuado, busca lenta, incompatibilidade com SSH e falta de suporte a terminal), o autor decidiu desenvolver por conta própria um novo editor de texto em TUI
  • Tentou 13 editores, incluindo Helix, VS Code, Vim, Neovim e Emacs, mas nenhum oferecia a sensação de uso (Fingerspitzengefühl) que ele buscava
  • No início, implementou apenas o mínimo de funcionalidades personalizado para uso pessoal, deixando desempenho, Unicode e suporte multilíngue para depois, e expandindo gradualmente
  • Durante o desenvolvimento, implementou diretamente seu próprio motor de regex, navegador de arquivos, renderização baseada em TUI e integração com buffer de terminal
  • Aplicou diversas técnicas de otimização de desempenho em busca no projeto inteiro, destaque de sintaxe, tratamento de cache e distribuição de trabalho multithread
  • Como resultado, concluiu uma ferramenta perfeitamente adaptada ao seu próprio fluxo de trabalho e afirma ter recuperado a produtividade e o prazer de programar

Limitações dos editores existentes e busca por alternativas

  • Os problemas do editor Howl, usado por cerca de 10 anos, foram o gatilho para começar a desenvolver um editor próprio
    • O desenvolvimento estava parado havia anos, então ele mantinha seu próprio fork, mas como o código era escrito em MoonScript, fazer mudanças profundas era difícil
    • O desempenho da busca de arquivos em todo o projeto era insuficiente, interrompendo o fluxo de trabalho
    • Por ser um editor GUI, não era possível usá-lo remotamente via conexão SSH
    • Não havia terminal integrado, então não dava para interagir ao vivo com comandos externos, e a maior parte dos códigos de escape ANSI não era suportada
  • Testou 13 editores, incluindo Helix, VS Code, Sublime Text, Vim, Zed, Neovim, Emacs, Geany, Micro, Lite XL, Lapce, GNOME Builder e Kakoune
    • Cada um tinha seus pontos fortes, mas nenhum atendia à sensação de uso (Fingerspitzengefühl) desejada
    • O Helix foi o que usou por mais tempo, mas perdeu o interesse depois de um mês

Estratégia inicial de desenvolvimento

  • No começo, limitou o escopo ao mínimo possível
    • Excluiu funcionalidades para outros usuários e deixou toda a configuração hardcoded
    • Adiou otimizações de desempenho e começou com um buffer baseado em String
    • Também deixou de lado o suporte completo a grafemas Unicode, julgando suficiente que o símbolo £ ocupasse uma única coluna
    • O destaque de sintaxe suportava só algumas poucas linguagens de uso frequente; para o restante, usou um destaque genérico baseado em delimitadores
  • Na segunda tentativa, construiu primeiro um pequeno framework TUI, mas com o tempo removeu a maior parte dele e mudou para uma abordagem mais direta e detalhada

Dogfooding na prática

  • Depois que o editor atingiu o limiar mínimo de funcionalidade para abrir, editar e salvar um único arquivo, ele passou a seguir três práticas
    • Em vez de nano, passou a usar seu próprio editor de forma forçada para editar arquivos do sistema ou escrever notas
    • Sempre que encontrava funcionalidades faltando, bugs, comportamentos estranhos ou limitações, registrava tudo no README.md do projeto
    • Problemas suficientemente irritantes eram corrigidos imediatamente
  • Essas três práticas fizeram o volume de trabalho crescer de 1 hora por mês para várias horas por semana
  • De um total de cerca de 10.000 linhas de código, quase tudo foi escrito nos últimos 6 meses

Manipulação de cursor

  • A manipulação de cursor é uma área difícil de implementar
    • Combinações de teclas como ctrl + shift + left parecem naturais para o usuário, mas a lógica por trás delas é complexa
  • O conselho central é implementar entradas de alto nível como combinações de operações primitivas
    • Ex.: backspace por palavra → mover o cursor por palavra + selecionar intervalo + deletar
  • Ao implementar undo/redo, essas 3 ações precisam ser agrupadas como uma só para garantir um resultado intuitivo
  • Isso ajudou a entender por que editores modais expõem diretamente essas operações primitivas ao usuário

Navegador de arquivos

  • O navegador de arquivos do Howl era o principal motivo pelo qual ele não conseguia migrar para outro editor
    • O filtro fuzzy com atualização imediata era excelente, permitindo encontrar o arquivo desejado quase sempre com apenas 1 ou 2 teclas
    • Se o arquivo não existisse, era possível criá-lo inline
    • Ao digitar ~/, o navegador mudava automaticamente para o diretório home
    • Também mostrava uma prévia do arquivo a ser aberto na janela principal de edição
  • Critica a forma como outros editores resolvem a abertura de arquivos com dependência de mouse, diálogos padrão do GTK e adivinhação de nomes de arquivo
  • Na implementação própria, concluiu que três critérios simples bastavam, em vez de métodos complexos como Levenshtein distance
    • Se o nome começa com a expressão de filtro
    • Se o nome contém a expressão de filtro
    • O horário mais recente de modificação/acesso
  • Permitiu correspondência sem distinção entre maiúsculas e minúsculas, mas com um leve ganho de prioridade quando as maiúsculas/minúsculas coincidiam exatamente
  • Mesmo em projetos com dezenas de milhares de arquivos, após digitar 2 teclas havia cerca de 95% de chance de o arquivo desejado estar entre os 2 primeiros resultados

Motor de regex

  • Regex é usada em três lugares: busca no projeto inteiro, destaque de sintaxe e busca dentro do buffer
  • Razões para implementar o motor por conta própria em vez de usar o crate regex-automata
    • Precisava lidar com edge cases sensíveis ao contexto, como a sintaxe de raw strings do Rust
    • O próprio projeto também era um exercício de construir e entender sua própria stack
  • A implementação inicial era lenta: analisava a sintaxe regex com o crate de parsing chumsky e percorria a AST a cada caractere
  • Depois, foi realizando otimizações em etapas
    • Otimizador single-pass: converte grupos recorrentes de correspondência de caracteres em um único nó String, permitindo buscas exatas por string
    • Extração de prefixo comum: por exemplo, em hel[(lo)p], detecta o prefixo comum hel e tenta casar apenas nessas posições → grande ganho na busca pelo projeto inteiro
    • Reimplementou o walker da AST como uma VM de threaded code baseada em chamadas dinâmicas do Rust
    • Converteu essa VM para o formato CPS (Continuation-Passing Style), em que cada instrução faz tail-call da próxima, aproveitando otimizações do compilador
    • Encapsulou as lentas chamadas dinâmicas de função do Rust sem lookup de vtable, reduzindo o codegen de muitos comandos regex a poucas instruções de máquina
    • Sempre que possível, implementou comandos regex em nível de byte em vez de codepoints Unicode; graças ao design do UTF-8, técnicas de otimização para ASCII também funcionavam em codepoints multibyte
  • Também tentou compilar para uma cadeia de jump LUTs, mas benchmarks mostraram ganho de apenas 20–30% sobre threaded code, com perda grande de flexibilidade, então não adotou
  • Resultado final: no destaque de sintaxe mais complexo para Rust, conseguiu destacar por completo um arquivo gerado automaticamente de 50.000 linhas em menos de 10 ms a partir de um estado limpo

Cache de destaque de sintaxe

  • No início, a estratégia era redestacar o arquivo inteiro a cada mudança, mas isso causava queda de desempenho em arquivos grandes
  • Implementou um cache sob demanda de destaque por tokens
    • O destaque é feito em chunks de tamanho aproximadamente igual
    • Quando há uma modificação (damage) no buffer, apenas os chunks sobrepostos à posição alterada ou posteriores são invalidados
  • Mesmo no pior caso (edição no meio de um arquivo grande), o estado de destaque antes da mudança é preservado, e o que está abaixo da área visível nem precisa ser processado, pois a informação não é requisitada
  • Como é uma abordagem orientada por demanda, também funciona corretamente com múltiplos painéis exibindo partes diferentes do mesmo buffer

Busca no projeto inteiro

  • O processo de busca tem 4 etapas
    • Determinar a raiz do projeto procurando um diretório .git/ ao subir a partir do diretório atual
    • Percorrer recursivamente todos os diretórios da raiz e casar o padrão de busca com o conteúdo dos arquivos
    • Para cada correspondência positiva, extrair um snippet do arquivo e aplicar destaque de sintaxe para a prévia do resultado
    • Definir a ordem dos resultados segundo a distância de navegação em relação ao caminho atual (arquivos mais próximos recebem maior prioridade)
  • Aplica regras padrão de filtragem para evitar diretórios de build e similares
  • O processamento é multithread, com distribuição de trabalho entre threads em um esquema básico de work-stealing
    • Resolveu o problema de detecção de término em uma estrutura especial em que todas as threads são consumidoras e produtoras
    • Threads em espera incrementam um contador atômico; quando ele chega ao número de workers e a fila está vazia, o processamento termina globalmente
  • Graças às otimizações de regex e à velocidade dos SSDs modernos, até em codebases grandes como Veloren a busca por padrões simples termina quase instantaneamente
  • No flamegraph, o comportamento aparece majoritariamente como IO-bound
  • Poder pesquisar grandes codebases na velocidade do pensamento dentro do editor contribui muito para a produtividade

Buffer do emulador de terminal

  • Em um editor baseado em painéis, é muito conveniente poder usar um painel como janela de terminal
  • Ele tentou implementar seu próprio parser ANSI, mas o suporte a recursos modernos de renderização de terminal, como OSC52 e a extensão de teclado Kitty, é vasto demais
  • Então passou a usar o crate alacritty_terminal para reutilizar o parser de sequências de escape e a lógica de gerenciamento de estado do emulador de terminal Alacritty
  • Como resultado, consegue substituir recursos centrais de screen/tmux e ainda oferecer suporte mais rico a sequências de escape

Otimização de renderização

  • Mesmo sendo baseado em TUI, a largura de banda em conexões móveis remotas ainda é importante
  • Double buffering: mantém duas cópias internas da tela do terminal
    • Ao redesenhar, compara com o frame anterior e emite sequências de escape ANSI apenas para as células alteradas
    • Sequências como movimento de cursor e mudança de modo de estilo também são emitidas só quando realmente necessário
  • Na maioria dos emuladores de terminal (com exceção do Ghostty), abrir um arquivo grande com cat no painel de terminal do editor e depois fechar o editor é mais rápido do que executar cat diretamente no terminal hospedeiro
    • Isso porque alacritty_terminal bloqueia o custo de processamento dos bytes enviados ao stdout do terminal hospedeiro

Conclusão: crie sua própria ferramenta

  • O editor criado por ele se tornou uma ferramenta perfeitamente ajustada ao seu fluxo de trabalho
  • Ele discorda da noção comum de que criar seu próprio editor ou ferramenta seja um sofrimento inútil
  • Aponta quatro vantagens
    • Personalização perfeita: faz exatamente o que ele quer, nem mais nem menos
    • Aprendizado técnico amplo: adquiriu compreensão profunda de regex, ANSI, pseudoterminal (pty), design de TUI, detalhes do UTF-8 e outras habilidades úteis de forma geral
    • Ganho de produtividade no longo prazo: por entender completamente sua ferramenta e embutir recursos ajustados ao fluxo pessoal, reduziu o atrito com as ferramentas
    • Prazer genuíno: resolver problemas autocontidos e sentir o resultado na ponta dos dedos reacendeu seu amor pela programação; ele diz que voltou a codar sorrindo e até rindo sozinho depois de anos
  • Mesmo que não seja um editor de texto, recomenda criar sua própria ferramenta e enfatiza a importância de aproveitar o desafio em si, sem terceirizar as partes difíceis para uma “caixa de estatística” (como IA)

5 comentários

 
xguru 2026-03-12

Na verdade, a coisa mais surpreendente neste texto é uma palavra.

Fingerspitzengefühl

Finger (dedo) + Spitzen (ponta) + Gefühl (sensação)

O alemão realmente... nossa... até tem uma palavra para descrever a sensação tátil na ponta dos dedos ao manipular algo.

 
carnoxen 2026-03-12

Então "Finger" também era alemão. Achei que fosse inglês...

 
mhcoma 2026-03-13

Como pertencem ao mesmo grupo lexical, compartilham muito vocabulário básico.

 
yangeok 2026-03-12

É o alemão, em que as combinações de palavras podem ser infinitas, hehe.

 
GN⁺ 2026-03-12
Comentários do Hacker News
  • Foi um prazer ler do começo ao fim. Tenho até recomendado aos amigos que façam seu próprio editor de texto
    Eu uso meu editor chamado “Left” há quase 10 anos. No começo ele não era perfeito, mas fui melhorando o Left editando o próprio Left com ele. A alegria que sinto toda manhã ao abrir uma ferramenta feita por mim compensa 20 vezes o tempo investido

    • Eu também uso um editor pessoal há mais de 10 anos. Passar o dia com uma ferramenta feita exatamente para mim é uma sensação muito confortável
    • Eu uso meu editor “aoeui” há 19 anos. Foi uma das escolhas que mais impactaram meu ganho de produtividade
    • Fiquei curioso para saber quais recursos foram mais importantes. Também queria saber se ele foi projetado para dar suporte a vários fluxos de trabalho
  • Existe um ditado: “Na vida, você deve construir uma casa, plantar uma árvore e fazer um editor”. Eu comecei pela última parte
    É uma frase do editor estilo Vi Vip, baseado em PicoLisp

  • Eu também fiz um editor de texto do zero. Como ele tem muitos recursos, usei bastante ferramentas externas como LSP, tree-sitter e fzf.
    Projetei para que fosse possível customizá-lo no estilo suckless, apenas alterando o código de forma simples.
    Nas primeiras semanas ele estava cheio de bugs, mas foi ficando cada vez mais estável à medida que eu corrigia. Dá para ver no meu projeto hat

    • Exato. É muito gratificante quando as correções e melhorias do passado se acumulam e viram aceleração de produtividade no futuro
  • Será que alguém pode recomendar uma boa biblioteca de edição de texto?
    GUI é indispensável, então eu teria que lidar diretamente com renderizador de fonte e contexto gráfico.
    Não me serve algo só para console, e se eu fizer só a GUI, não terei funcionalidade de edição, então preciso dos dois.
    Surpreendentemente, é difícil encontrar uma biblioteca em forma de API pura que atenda a esses requisitos.
    A maioria é um editor completo, ou algo no nível de um framework enorme.
    Eu só queria um mecanismo básico de edição que conseguisse lidar rapidamente com arquivos de texto grandes

    • Fiquei surpreso com o quanto os emuladores de terminal estão poderosos hoje em dia. Dá para fazer quase tudo: área de transferência, eventos de mouse, rastreamento de foco, notificações etc.
      Com uma ferramenta como trolley, também dá para empacotar isso como uma UI nativa baseada em ghostty
    • Vários editores GUI leves são construídos sobre o Scintilla. Ele suporta GTK, Windows e Mac. Mas, como tem muitos recursos, pode ser demais para usar como uma API simples
    • Existe também o stb_textedit.h, mas eu não recomendaria. Há muitas limitações, como no tratamento de UTF-8 e na detecção de limites de palavras.
      Em vez disso, a combinação SDL com SDL_ttf é uma opção bem decente. O SDL3_ttf também melhorou no tratamento de strings
    • Dependendo da plataforma, se o objetivo não for renderização de GUI, o raylib pode ser uma boa alternativa
  • Reimplementei o editor “kilo”, do antirez.
    O código original e o tutorial são muito bons, então foi um excelente projeto para aprender o básico de modo terminal e da linguagem C

  • Tenho lembranças de ter feito meu próprio editor nos anos 90 para arquivos COBOL e ASM.
    Tinha realce de sintaxe, buffering rápido e até protetor de tela.
    Rodava em um Pentium 120 e, na minha memória, era mil vezes mais rápido que o VSCode de hoje

    • Eu também fiz um editor em VB6. Na página de marketing de 2002, havia uma lista de recursos como “templates ilimitados, impressão colorida, localizar/substituir com regex, completação de código”.
      Naquela época, a gente escrevia todas as tags HTML em maiúsculas
    • Quando abro o VSCode em um notebook antigo, dói de tão lento. Eu sou da geração do vim, mas sinto que hoje em dia é difícil recomendar isso para as pessoas
    • Só como referência, o Borland Turbo Pascal e o Turbo C também conseguiam abrir vários arquivos ao mesmo tempo
  • Este é o editor zte, feito pelo autor do texto

  • A frase “resista à tentação de empurrar as partes difíceis para dentro de uma caixa estatística” realmente me marcou

  • Eu também uso meu próprio editor. As outras pessoas não ligam muito, mas o valor que tiro de uma ferramenta feita por mim é enorme

    • Eu também uso um editor feito na minha própria linguagem de programação. Ainda bem que não preciso fazer meu próprio sistema operacional também
    • Eu modifiquei um editor existente para adaptá-lo ao meu gosto. Ele também tem carregamento de imagens, scripting e realce de cores para correspondência de tags HTML.
      Tem até uma função simples de “navegador” para abrir links com F5
    • Você não deixou o link :(
    • Eu também uso meu editor. Sempre que amigos olham para a tela e perguntam “o que é isso?”, eu fico orgulhoso
  • Josh Barretto é o gênio que fez o port de Super Mario 64 para GBA. Eu certamente toparia experimentar um editor dele