Montei minha config do GNU Emacs ao longo dos anos.
Tenho mantido esse repositório atualizado de tempos em tempos: https://github.com/alissonperez/emacs-conf
Dicas
Criar/abrir arquivo com nome parcial quando existe um nome parecido (Ivy)
Problema: ao usar C-x C-f (counsel-find-file) para criar um arquivo cujo nome é prefixo de outro já existente (ex.: digitar .env quando já existe .env.example), o Ivy destaca/seleciona o arquivo existente na lista, e apertar RET acaba abrindo esse arquivo em vez de criar o novo com o nome digitado.
Solução: C-M-j (ivy-immediate-done). Esse atalho já vem por padrão no ivy-minibuffer-map e ignora o candidato destacado, usando exatamente o texto digitado na minibuffer.
Fluxo:
C-x C-f- Digite
.env - Mesmo com
.env.exampledestacado na lista, aperteC-M-j - O Emacs cria/abre
.envliteral, ignorando a sugestão
Tecla Meta não funciona no terminal (Ghostty)
Problema: rodando o Emacs no terminal (emacs -nw) dentro do Ghostty, atalhos com Meta (ex.: M-x, M-p, M-n) não funcionam ao apertar Option. Isso acontece porque, por padrão no macOS, o Ghostty reserva a tecla Option para digitar caracteres especiais (á, é, ç, etc.) e não a envia como Alt/Meta para o Emacs.
Solução: adicionar ao config do Ghostty (~/.config/ghostty/config):
macos-option-as-alt = true
Reiniciar o Ghostty para aplicar. Alternativa: usar macos-option-as-alt = left ou right para manter apenas uma das teclas Option como Meta e preservar a outra para acentuação.
Ctrl+Shift+letra não funciona no terminal dentro do tmux
Problema: no terminal, C-S-d (duplicar linha) se comporta como C-d, e a seleção com C-S-f/C-S-b/C-S-p/C-S-n não funciona. A codificação clássica de terminal não tem bit de Shift para combinações com Control: C-S-d e C-d chegam como o mesmo byte.
Fora do tmux isso é resolvido pelo pacote kkp, que faz o Emacs falar o Kitty Keyboard Protocol do Ghostty. Dentro do tmux o kkp nunca ativa: ele só se habilita depois de perguntar ao terminal (CSI ? u) e receber uma resposta válida, e o tmux não responde a essa pergunta (extended-keys-format não aceita o valor kitty).
A solução exige três peças alinhadas — faltando qualquer uma, não funciona:
1. tmux precisa pedir as teclas estendidas ao Ghostty e repassá-las. Em ~/.tmux.conf:
# Pede eventos de teclado estendidos ao terminal externo. Sem a feature
# "extkeys" o tmux nem solicita esses eventos, então não tem o que repassar.
# O nome do terminal precisa bater com o que você usa (aqui, xterm-ghostty).
set -as terminal-features ',xterm-ghostty:extkeys'
# Reporta teclas modificadas aos programas rodando dentro do painel.
set -s extended-keys on
# csi-u, não xterm — ver detalhe sobre formato mais abaixo.
set -s extended-keys-format csi-uEsse arquivo fica fora do repo do Emacs, então deixei uma cópia versionada em examples/tmux.conf lá, referenciada no README.
2. O Emacs precisa pedir o modo 2 do modifyOtherKeys. O term/tmux.el pede o modo 1, que por definição só re-codifica teclas “sem representação bem-conhecida” — e C-S-d tem uma (C-d), então continua ambígua. Isso é hardcoded no Emacs, não há variável para mudar; é preciso mandar \e[>4;2m manualmente.
3. Um decodificador genérico. O modo 2 re-codifica todas as teclas modificadas (M-x vira \e[120;3u, C-c vira \e[99;5u), e o xterm.el só decodifica uma lista curada — o resto vazaria como texto literal no buffer. O parser do kkp resolve isso e é stateless: só a detecção dele depende do handshake, não o parsing. Dá para registrá-lo direto.
O bloco correspondente está no init.el, sob a seção “Kitty Keyboard Protocol”.
Detalhe que custou caro ao depurar: o formato importa. O parser do kkp entende a codificação do Kitty, que corresponde ao formato csi-u do tmux (\e[100;6u) e não ao formato xterm (\e[27;6;100~, que ele leria como keycode 27).
Outro detalhe traiçoeiro: tmux send-keys C-S-d gera bytes diferentes de um toque real. O send-keys manda o código 100 (d minúsculo); o Ghostty manda 68 (D, a letra já com Shift). Testar com send-keys dá falso positivo — para medir de verdade, capture os bytes de um toque real:
printf '\033[>4;2m'; stty raw -echo; dd of=/tmp/k.bin bs=1 count=12 2>/dev/null; stty sane; od -c /tmp/k.bin
Para inspecionar o estado: tmux list-panes -a -F '#{pane_current_command} #{pane_key_mode}' mostra o modo negociado por painel (VT10x = legado, Ext 2 = modo 2 ativo).