Como obter efeitos de dobramento de código no Emacs?

123

Qual é a melhor maneira de conseguir algo como dobramento de código ou o tipo de ciclo que o modo org usa. Qual seria a melhor solução no elisp para criar este tipo de comportamento?

EDIT: Desculpe, não fui claro. Eu quero programar algo em elisp que faz coisas muito semelhantes à dobra de código ou, na verdade, mais como o modo org com a hierarquia que pode ser expandida. Estou me perguntando a melhor maneira de conseguir esse efeito. Acho que ouvi que as sobreposições do emacs são uma boa solução, mas não sei.

No que diz respeito a dobrar, eu apenas uso o display integrado de seleção

EDITAR NÚMERO 2:

Obrigado pelas respostas, mas acho que estou fazendo a pergunta errada, então deixe-me tentar ser mais claro sobre o que estou tentando fazer. Eu gostaria de criar o seguinte

Quando você coloca seu ponto em uma função e chama esta função elisp, ela colocará a definição da função de onde quer que esteja (estou pensando em usar apenas find-tag para isso) e a desdobrará no buffer atual. A ideia é que se você tiver que pular para um buffer diferente para ler a definição da função, eu sinto que é uma mudança de contexto para outro arquivo. Então, eu gostaria que ele se comportasse como dobramento de código, apenas puxando código externo do buffer. Isso apresenta alguns problemas, pois não é possível colar o código de forma aguda no buffer ou, se alguém salvá-lo, salvará o código puxado. Portanto, gostaria de saber se existe uma maneira de criar uma área dentro de um buffer que também não faz parte do buffer. Eu acho que faz sentido.

Jacob
fonte
Você está procurando por algo que quando você chama com ponto em uma função CALL salta para a definição da função? mais ou menos como obter ajuda sobre uma função elisp permitirá que você pule para o código elisp? Não acho que você possa fazer isso sem algum conceito de "O projeto". Por exemplo, como você saberia para qual função de "troca" deseja pular?
Brian Postow
1
Veja também: stackoverflow.com/questions/382781/… onde a exibição seletiva é ajustada um pouco para alguns efeitos de dobradura.
Michael Paulukonis
Eu recomendo que você remova o seu EDIT NB 2e faça uma nova pergunta para ele.
Stefan

Respostas:

151

Geralmente, dobrar é desnecessário com o emacs, pois ele tem ferramentas que implementam explicitamente as ações que as pessoas fazem manualmente ao dobrar o código.

A maioria das pessoas tem bom sucesso com pesquisas incrementais simples. Vê "foo" mencionado em algum lugar? Digite C-sfoo, encontre a definição, pressione Enter, leia-a e pressione C-x C-xpara voltar para onde estava. Simples e muito útil.

A maioria dos modos suporta imenu . M-ximenupermitirá que você pule para uma definição de função (etc.) por nome. Você também pode vinculá-lo a um clique do mouse para obter um menu de funções (ou adicioná-lo à barra de menus; consulte a página Informações para obter mais detalhes). Ele fornece dados para o modo de função qual, o que permitirá que você veja em qual função você está atualmente na linha de modelo. (Por que suas funções são tão longas, então?)

Também existe a barra de velocidade , que exibe as informações do imenu (e outras coisas) graficamente.

Se você deseja obter uma visão geral do seu arquivo, tente M-xoccur ". Dado um regex, ele criará um novo buffer com cada correspondência no buffer atual. Você pode pesquisar por" (defun "para obter uma visão geral das funções do arquivo atual Ao clicar no resultado, você será movido para essa posição no arquivo.

De qualquer forma, pense sobre o que você realmente deseja alcançar, e o Emacs provavelmente implementa isso. Não lute com ferramentas imperfeitas que o fazem dobrar e desdobrar coisas constantemente.

Jrockway
fonte
13
O Vim também fornece todos esses recursos de uma forma ou de outra, mas ainda acho seu recurso de dobramento de código inestimável.
intuído em
115
Eu votei contra a primeira frase ("Folding é geralmente desnecessário com emacs, como ..."). Eu uso a dobradura simples (com base no nível de indentação) constantemente para verificar a estrutura do código desconhecido.
Simon Michael
4
Ms o é o atalho para Mx ocorrer
Joshua Olson
3
Votei porque muitos atalhos úteis na resposta, mas também votei positivamente no comentário de @SimonMichael porque dobrar / desdobrar ainda pode ser útil às vezes!
Adrien Coquio
56
A resposta foi bem pensada e muito informativa. No entanto, o OP perguntou como fazer a dobragem de código. O OP não perguntou qual era a maneira favorita de todos de evitar o dobramento de código. Votado para baixo.
wkschwartz
104

modo ocultar-mostrar ( hs-minor-mode) com atalho C-c @ C-M-hde teclado padrão para acionar o dobramento ( hs-hide-all)

dmckee --- gatinho ex-moderador
fonte
12
Isso funciona bem. E com-mode mal, este é acionado pelos comandos normais Vim: zR, zM, zo, zc.
Justin M. Keyes
39

Outra maneira de tirar a pele do gato:

Acontece que você não precisa de nenhum pacote ou configuração extra para isso. Vá para qualquer arquivo de origem, digite

M-1 Cx $ e mágica acontece!

Como de costume, é magia branca: Cx $ trará seu código de volta.

Podemos usar o sistema de ajuda do Emacs para descobrir o que está acontecendo: Ch k Cx $ nos diz que a combinação de teclas acima está chamando set-selected-display , uma função que leva um argumento numérico (o prefixo M-1 passa 1 como o valor desse argumento) e, sem surpresa, define a variável selected-display com o valor desse argumento.

do blog de magia do emacs menor

Apenas para completar: M-3 Cx $ mostraria código aninhado mais profundo e assim por diante.

FWIW Eu fiz um pequeno ajudante hoje baseado em smth. encontrado aqui para que F5 alterne a dobradura de código com base na posição atual do cursor:

(global-set-key (kbd "<f5>") 'set-selective-display-dlw)

(defun set-selective-display-dlw (&optional level)
"Fold text indented same of more than the cursor.
If level is set, set the indent level to LEVEL.
If 'selective-display' is already set to LEVEL, clicking
F5 again will unset 'selective-display' by setting it to 0."
  (interactive "P")
  (if (eq selective-display (1+ (current-column)))
      (set-selective-display 0)
    (set-selective-display (or level (1+ (current-column))))))
einSelbst
fonte
22

Eu uso o modo de contorno menor para dobrar meu código Python. Em vez de precisar colocar {{{e}}} como no modo dobrável, ele usa onde o bloco está definido.

http://www.gnu.org/software/emacs/manual/html_node/emacs/Outline-Mode.html http://www.emacswiki.org/emacs/OutlineMinorMode

Tenho certeza de que vem com o emacs. Em seguida, adiciono isso ao meu .emacs

;;======= Code folding =======
(add-hook 'python-mode-hook 'my-python-outline-hook)
; this gets called by outline to deteremine the level. Just use the length of the whitespace
(defun py-outline-level ()
  (let (buffer-invisibility-spec)
    (save-excursion
      (skip-chars-forward "    ")
      (current-column))))
; this get called after python mode is enabled
(defun my-python-outline-hook ()
  ; outline uses this regexp to find headers. I match lines with no indent and indented "class"
  ; and "def" lines.
  (setq outline-regexp "[^ \t]\\|[ \t]*\\(def\\|class\\) ")
  ; enable our level computation
  (setq outline-level 'py-outline-level)
  ; do not use their \C-c@ prefix, too hard to type. Note this overides some bindings.
  (setq outline-minor-mode-prefix "\C-t")
  ; turn on outline mode
  (outline-minor-mode t)
  ; initially hide all but the headers
  ;(hide-body)
  ; make paren matches visible
  (show-paren-mode 1)
)
Nikwin
fonte
8
parece que outline-modesuporta python fora da caixa no emacs 24 - sem necessidade de outline-levelfunções personalizadas . Isso é tudo que eu precisava adicionar ao meu user.el:(add-hook 'python-mode-hook 'outline-minor-mode)
scytale
1
Ah, e você definitivamente deseja substituir outline-minor-mode-prefix- os atalhos de teclado padrão são horríveis - eu uso(setq outline-minor-mode-prefix (kbd "C-;"))
scytale
13

Você também pode obter o dobramento de código usando CEDET com o seguinte código no arquivo init:

(global-semantic-folding-mode t)

Após a avaliação deste código, o pequeno triângulo aparecerá na área fringle, então você poderá dobrar e desdobrar o código usando-o. Este método é mais preciso, pois utiliza informações sintáticas, extraídas do código-fonte

Alex Ott
fonte
1
se estiver enfrentando algum bug, dê uma olhada nesta questão: stackoverflow.com/questions/15307113/…
AdrieanKhisbe
9

o modo hs-minor funciona perfeitamente.

Funciona ainda mais bem quando combinado com fold-dwim (faça o que quero dizer). Depois, há o fold-dwim-org, que fornece atalhos de teclado como o modo org para dobrar código! Ambos podem ser instalados via marmelada (e eu acho que elpa).

Jones
fonte
5

vimish-fold também é uma solução fácil e agradável.

https://github.com/mrkkrp/vimish-fold .

Na página inicial:

Este é um pacote para realizar a dobragem de texto como no Vim. Possui os seguintes recursos:

  • dobramento de regiões ativas;
  • bom feedback visual: é óbvio qual parte do texto está dobrada;
  • persistência por padrão: quando você fecha o arquivo, suas dobras não desaparecem;
  • a persistência é bem dimensionada, você pode trabalhar em centenas de arquivos com muitas dobras sem efeitos adversos;
  • não quebra a indentação ou algo assim;
  • as dobras podem ser alternadas do estado dobrado para desdobrado e voltado com muita facilidade;
  • navegação rápida entre dobras existentes;
  • você pode usar o mouse para desdobrar dobras (bom para iniciantes e não apenas para eles);
  • para os fãs do pacote avy: você pode usar avy para dobrar o texto com um número mínimo de pressionamentos de tecla!

Usando o excelente use-packageeu instalo e ativo usando este trecho na minha configuração:

(use-package vimish-fold
  :ensure t
  :config (vimish-fold-global-mode t))
Horus
fonte
3

Estou surpreso que ninguém tenha mencionado o estreitamento-alargamento. É super incrível, ele vem com o emacs também. Basta selecionar o código que você deseja focar e pressionar C-x n n, para voltar ao modo de visualização completa, basta fazer C-x n w. Eu sempre prefiro usar a funcionalidade embutida do emacs do que entulhar meu espaço do usuário com outro pacote. Se o emacs pode fazer isso com funcionalidade embutida, então eu prefiro isso a algum pacote de terceiros, mas isso é só comigo, não significa ou implica em nada além de que eu gosto de coisas simples em vez de configurações longas complexas.

Kirk Walla
fonte
2

Eu acredito que a sua comparação do seu "projeto" com a dobra não é muito boa, porque a dobra é sobre mudar a aparência enquanto mantém o conteúdo do buffer intacto (o texto). Seu projeto envolveria a exibição de texto extra, mantendo o conteúdo do buffer intacto, AFAIU. Assim. não é implementável como uma composição de inserção de texto e dobramento (então, o conteúdo do buffer seria alterado).

Mas talvez seja realmente possível com o mesmo mecanismo que a dobragem é feita com - "sobreposições" ... Considere as propriedades de sobreposição "antes da string" e "depois da string" ; talvez você pudesse colocar suas definições de função nessas strings pertencentes a uma sobreposição de comprimento zero no ponto. Observe a função de contorno-bandeira-região para ver como as sobreposições são usadas no modo contorno.

imz - Ivan Zakharyaschev
fonte
2

Se você usar hs-minor-mode, pode ser uma boa ideia definir também um atalho mais conveniente, por exemplo:

(eval-after-load 'hideshow
 '(progn
   (global-set-key (kbd "C-+") 'hs-toggle-hiding)))
Quazgar
fonte
0

Com inspiração na resposta de einSelbst :

(conselho-add 'set-seletivo-display
            : filter-args (lambda (args)
                           (if (or (car args) select-display)
                               args
                             (lista (1+ (coluna atual)))))
            '((nome. set-selected-display-from-cursor-column)))

Voila, C-x $de repente tornou-se útil, mesmo sem C-unem M-4negócio.

DomQ
fonte
0

Se estiver fazendo JavaScript e usando js2-mode.el, você pode:

C-c C-f: alternar ocultar / mostrar tudo

C-c C-e: ocultar elemento

C-c C-s: mostrar elemento

Roboli
fonte