1 pontos por GN⁺ 2026-05-13 | 2 comentários | Compartilhar no WhatsApp
  • Um relato prático de migração, substituindo completamente um ambiente LSP baseado em lsp-mode que já funcionava bem pela solução LSP nativa do GNU Emacs, o Eglot
  • Em comparação com o lsp-mode, o Eglot oferece uma interface mais minimalista e silenciosa e se integra a pacotes externos como Corfu, Consult e Flycheck por meio da API padrão do Emacs Lisp
  • A maior parte da transição foi gasta não na configuração do próprio Eglot, mas em explorar, configurar e testar pacotes auxiliares
  • Para servidores LSP como pylsp e gopls, a forma de configurar o workspace varia; para configurações por projeto, é preciso usar .dir-locals.el
  • Como o Eglot vem embutido no GNU Emacs, vale a pena considerar a migração no longo prazo para quem usa Emacs

Motivação da migração e impressão geral

  • Sem um motivo especialmente forte, o autor começou a testar o Eglot após a migração para o Corfu e acabou seguindo em frente
  • lsp-mode + lsp-ui formam uma interface carregada (busy), com muitos tipos de informação exibidos ao mesmo tempo; a troca foi feita em busca de uma experiência LSP mais discreta
  • O Eglot é mais minimalista que o lsp-mode, mas para uma experiência completa é preciso reforçar recursos com pacotes adicionais
  • No fim, o resultado foi satisfatório e, nos modos Go e Python, recursos como “autocompletar por prefixo comum” passaram a funcionar melhor
  • Até daria para ajustar mais a configuração do lsp-ui, mas a migração para o Eglot resolveu todos os problemas de uma vez

Integração com pacotes auxiliares

  • Corfu funciona para autocompletar com a configuração existente, sem ajustes extras
  • Para obter uma prévia no estilo do lsp-ui em referências cruzadas, é preciso integrar o pacote consult e definir xref-show-xrefs-function como consult-xref
  • Depois de avaliar entre Flycheck e Flymake, a escolha acabou sendo o Flycheck
    • O Flymake se integra melhor ao Eglot, mas no geral a preferência continua sendo pelo Flycheck
    • Como o Eglot ativa flymake-mode automaticamente, foi necessário adicionar flymake a eglot-stay-out-of para desativá-lo
    • Como o modo global de flycheck-eglot não funcionou de forma estável, foi adotada uma configuração manual via hook

Configuração de atalhos de teclado

  • O Eglot não fornece atalhos padrão, então é preciso defini-los manualmente
  • Exemplos de atalhos atualmente em uso:
    • C-c reglot-rename, C-c oeglot-code-action-organize-imports
    • C-c heldoc, C-c aeglot-code-actions, C-c qeglot-code-action-quickfix
    • C-M-<mouse-2>eglot-code-actions-at-mouse (um atalho de mouse para contornar limitações de integração do flycheck-eglot)
  • eglot-format foi deliberadamente deixado sem atalho — em Go, já se usa o gofmt do go-mode
  • Ao definir eglot-extend-to-xref como t, após saltar para um item externo fica possível usar M-? para buscar outros usos dentro do projeto

Inicialização automática do servidor LSP

  • A documentação oficial do Eglot recomenda inicialização manual, mas aqui foi configurado para iniciar automaticamente apenas em arquivos locais
  • Foi definida a função eglot-ensure-local-only, que verifica se o arquivo é remoto com file-remote-p antes de chamar eglot-ensure
  • Limitação do eglot-ensure: quando há vários servidores LSP para uma mesma linguagem (por exemplo, pylsp e ruff no Python), ele escolhe automaticamente apenas o servidor padrão; para trocar, é preciso encerrar o servidor atual e chamar eglot manualmente
  • Para rodar vários servidores LSP ao mesmo tempo, é possível usar um multiplexador como o rassumfrassum

Acessibilidade de Code Actions

  • Há muitos code actions fornecidos pelos servidores LSP, mas no Eglot é difícil acessá-los de forma conveniente (o mesmo vale para o lsp-mode)
  • Os servidores LSP só fornecem code actions quando solicitados, e elas dependem de uma posição específica
  • O Eglot não oferece filtragem da longa lista de code actions enviada pelo servidor, o que deixa a lista confusa tanto em Go quanto em Python

Configuração de workspace no pylsp

  • No pylsp (servidor Python LSP), para desativar linters baseados em estilo nos diagnósticos permanentes, é necessário usar eglot-workspace-configuration
  • O lsp-mode oferece controles convenientes para desligar ferramentas de diagnóstico individuais, como mccabe, mas no Eglot é preciso escrever manualmente a workspace configuration em formato JSON
  • Exemplo: desativar mccabe, pylint, mypy, pycodestyle etc. com :enabled :json-false
  • As chaves relacionadas ao mypy aparecem misturadas sob dois nomes, pylsp_mypy e mypy, o que reflete detalhes da implementação interna do pylsp
  • É obrigatório usar setq-default; com setq isso não funciona

Configuração por projeto e .dir-locals.el

  • O Eglot não tem um método conveniente para definir temporariamente parâmetros do servidor LSP por projeto
  • Quando uma configuração específica é necessária, o jeito mais simples é escrevê-la no formato correto em .dir-locals.el
  • Em gopls (Go) e pylsp (Python), a estrutura de configuração é completamente diferente, exigindo aprendizado individual para cada servidor LSP
  • Para alterar configurações em tempo de execução, é preciso escrever uma função dedicada que defina uma nova classe com dir-locals-set-class-variables, depois chame dir-locals-set-directory-class e eglot-signal-didChangeConfiguration
  • Como o Eglot executa um único servidor LSP para o projeto inteiro (a árvore de diretórios), não é possível configurar LSP por arquivo ou buffer; a aplicação tem de ser por projeto
  • Se eglot-workspace-configuration for definido por meios comuns, ele vira uma variável local de buffer e na prática se torna inútil

Experiência com Flymake vs Flycheck

  • O Flymake se integra melhor ao Eglot e mostra diretamente nos diagnósticos sugestões de correção vindas do servidor LSP (quickfix code actions) no menu pop-up do botão 2
  • O Flycheck apenas marca os erros, com a limitação de exigir disparo separado das code actions do LSP
  • A princípio houve migração para o Flymake, mas como o Flycheck tem vantagens em alguns pontos, as duas configurações foram mantidas
  • O autor do flycheck-eglot sugeriu uma solução alternativa para esse problema, permitindo voltar ao Flycheck
  • O Flycheck tem uma coleção maior de checkers que o Flymake e facilita mais a troca entre eles
  • Faz falta no Flymake a opção de “mostrar diagnósticos no fim da linha”
    • flycheck-inline mostra apenas avisos na posição atual e não exibe todos os avisos durante a rolagem
    • Sideline + sideline-flycheck têm a mesma limitação, mas oferecem uma experiência de UI melhor

2 comentários

 
GN⁺ 2026-05-13
Opiniões no Lobste.rs
  • Dependendo da linguagem, a recomendação de iniciar o Eglot automaticamente pode ser catastroficamente ruim. Os servidores LSP de muitas linguagens não são seguros para uso com código não confiável, e só de abrir os arquivos de um projeto Rust ou Elixir controlado por um atacante sua máquina pode ser comprometida
    A menos que seja uma linguagem com um servidor LSP conhecido por ser seguro, é melhor evitar a ativação automática do LSP. Referência: https://rust-analyzer.github.io/book/security.html

    • Se você vai inspecionar código potencialmente hostil, no fim das contas todo o trabalho precisa acontecer dentro de uma fronteira de segurança real. Até git status pode ampliar a superfície de ataque: https://github.com/justinsteven/advisories/…
      A diferença é que, no caso acima, o repositório em si precisa conter o exploit, enquanto no LSP o problema também pode vir do lado das dependências. Ainda assim, se você se acostuma a ligar o LSP por padrão, parece difícil evitar ficar dessensibilizado aos avisos
    • Outro motivo para evitar a inicialização automática é que alguns servidores de linguagem têm exigências altas de recursos. Em um projeto Rust de porte médio, só abrir um arquivo por alguns instantes já pode fazer um processo rust-analyzer de 4 GB rodar por vários minutos e criar um diretório target/debug/ com mais de 1 GB
    • De qualquer forma, no momento em que você roda cargo build, de certa forma já era. Claro, há uma grande diferença entre carregar o LSP automaticamente e um comando executado explicitamente pelo usuário, mas no uso real essa diferença talvez seja menor do que parece
    • Se você quer automação, é melhor fazer como o lsp-mode: perguntar antes de ativar e adicionar o projeto a uma lista de permissões. Se você já tem um hook que “executa automaticamente”, dá para fazer ele primeiro perguntar com read-from-minibuffer “você confia nesta pasta?” em umas 10 linhas, e usar algo como projectile para definir o diretório-base já traz a maior parte do ganho de segurança
      Minha configuração usa a lista de permissões do lsp-mode, mas a limpa a cada sessão, então sempre que reabro o Emacs preciso consentir de novo por projeto. Acho que originalmente fiz isso por desempenho, e houve casos em que o lsp-mode subia vários processos antes mesmo de eu abrir um projeto específico. O risco de segurança é real, mas não é tão difícil montar um fluxo de trabalho razoável
  • O ponto mais irritante do Eglot é que ele não expõe a maioria dos comandos como funções e os define sobre interfaces do Emacs como xref. Em casos como Clojure, quando há backends xref tanto do CIDER quanto do clojure-lsp, acabo preferindo o lado do CIDER, que conhece o estado real em tempo de execução do código carregado
    A análise estática do clojure-lsp pode se dessincronizar, especialmente em fluxos de trabalho com REPL remota. No lsp-mode, você pode chamar diretamente comandos como ir para definição e continuar usando xref, mas no Eglot é bem trabalhoso excluir apenas um backend xref específico. Outros comandos presentes no lsp-mode também faltam no Eglot, embora na prática sejam recursos que poderiam ser oferecidos por pontos de integração do Emacs parecidos com xref

  • Usei lsp-mode uma vez, mas apareceram tantos pop-ups e notificações confusas que removi na hora. O Eglot oferece uma experiência de LSP muito mais silenciosa
    Você pode deixá-lo ligado e usar os recursos quando estiver pronto. É interessante como ~cks aborda isso vindo da direção oposta e menciona várias dicas e alternativas

    • Eu desligo muitos recursos no lsp-mode e consigo usá-lo com uma interface bem silenciosa. Tentei migrar para o Eglot, mas não parecia ter as integrações que eu queria, então não fui muito além naquela época
      O que eu realmente queria encontrar é um servidor LSP capaz de lidar com repositórios muito grandes. Isso tem sido um limite frequente, e às vezes penso se eu deveria criar algo que processe a maior parte da indexação do código-fonte de uma vez e depois a reutilize para várias tarefas no estilo LSP, mas fico na dúvida se isso não seria tentar ferver outro oceano
  • Eglot e lsp-mode são os clientes LSP para Emacs mais conhecidos, mas também existem alternativas como lspce e lsp-bridge
    Usei o Eglot com satisfação por vários anos, mas ele tem uma limitação de projeto que pode virar um problema maior no futuro. Ele assume um cliente por buffer; isso fazia sentido quando o Eglot foi criado, mas agora está ficando cada vez mais comum querer rodar vários servidores LSP em um único buffer. A [recomendação] atual é usar um programa separado como multiplexador de LSP

    • Para esse fim existe isto
  • Há 4 dias migrei de lsp-mode para Eglot no Python e estou satisfeito
    Publiquei aqui uma versão mínima da configuração atual: https://discuss.afpy.org/t/configuration-emacs-minimale-en-2026/3001

    • Há quase um ano mudei de elpy para eglot + basedpyright, e também estou bem satisfeito
      Ainda assim, há alguns incômodos com autocompletar. Por exemplo, quando pressiono foo<tab><tab>, às vezes o basedpyright faz autoimport de alguma coisa estranha mesmo quando já existe um símbolo adequado no escopo atual, e ainda não encontrei uma forma de completar só até a maior substring comum. Fora isso, está bem bom
  • Tenho inveja de quem consegue usar o Emacs como uma IDE moderna. Eu uso os atalhos do Emacs, mas mesmo investindo 6 a 8 horas nunca consegui fazê-lo funcionar como IDE
    No passado tentei ajustar tudo para FB Flow, que eu usava no lugar de TypeScript em ambientes de desenvolvimento Linux e FreeBSD, e desisti; no fim de semana passado tentei de novo montar um ambiente Python completo no Windows com tree-sitter, e desisti outra vez. Há coisa demais para configurar, e também é preciso baixar DLLs demais, como os parsers do tree-sitter, então o que é necessário para transformá-lo em uma IDE de verdade parece excessivo. Já não quero mais investir esse tempo, mas ainda gosto do fato de poder digitar emacs -nw em qualquer terminal e ter aquele ambiente de edição familiar

    • Para Python, dá para começar muito bem só com uma configuração mínima de fido-vertical-mode, which-key-mode, global-completion-preview-mode, yasnippet, eglot-ensure e basedpyright
      Se o basedpyright estiver no PATH, você terá autocompletar e destaque de sintaxe decentes mesmo sem gramática tree-sitter. Isso é uma versão reduzida ao mínimo da minha configuração completa, e a configuração inteira está em my full config
    • Vale a pena experimentar o doom emacs. A configuração é muito fácil e, no estado padrão, a maior parte das coisas já funciona bem. Se você não gostar do evil-mode, também pode voltar para os atalhos do Emacs