Tecla "quick-view" direcionada para visualizar o arquivo no ponto

19

Eu gostaria de criar uma função que faça uma "visualização rápida" de um arquivo que está sendo apontado no diretório.

A maneira que eu gostaria que isso funcionasse é mantendo pressionada uma tecla de função, o que torna o arquivo visível em um buffer, mas quando a solto, o buffer fecha e o buffer direcionado retorna. Não quero ter que fechar o buffer temporário com C-x k .

Existe uma maneira de fazer essa funcionalidade no Emacs? Parece possível se eu puder vincular funções a pressionar / pressionar.

Eric Brown
fonte
1
Você não pode vincular para pressionar os eventos de pressionamento, mas essa funcionalidade pode definitivamente ser invadida com o uso de um mapa personalizado e um timer.
Jordon Biondo 25/09
Você está falando de uma nova janela aparecendo com uma visualização? Ou o conteúdo do buffer seria exibido na janela direcionada enquanto a tecla estiver pressionada?
Nispio 25/09
1
Existem esforços para nos permitir vincular a eventos? Eu quero esse recurso.
Wdkrnls 22/10/14

Respostas:

9

Aqui está minha maneira super hacky de simular a ligação de eventos de down / up de chave, aproveitando os temporizadores.

No geral, eu sugeriria seguir a resposta da Sigma, mas você pediu uma maneira de fechar a pré-visualização deixando ir, então sou obrigado a tentar.

Basicamente, o que você pode fazer é vincular alguma função que será sua função "keydown" a uma combinação de teclas e, dentro dessa ação, iniciar um timer ocioso que execute uma função que é sua função "keyup", desde que você mantenha pressionado o botão dadas as teclas, a função "keydown" será acionada repetidamente e isso inibirá a execução dos temporizadores ociosos. É claro que você precisa compensar o fato de que o comando será acionado repetidamente, provavelmente religando a tecla a algum tipo de função noop na função "keydown" e, em seguida, religando a função "keydown" na função "keyup".

Portanto, para o seu caso de uso, a função "keydown" abrirá um buffer de visualização com o conteúdo do arquivo no ponto e nesse buffer de visualização vinculará a mesma combinação de teclas a algum comando noop like. Sua função "keydown" também iniciará um timer ocioso que excluirá seu buffer de visualização e restaurará você de volta onde estava.

Para encurtar a história, aqui está o código:

Vincule esta função a uma combinação de teclas (que eu usei C-M-v); quando você a pressiona sobre um nome de arquivo, ele abre um novo buffer exibindo o conteúdo do arquivo no momento; quando você o solta, volta para o original. amortecedor.

(setq lexical-binding t)

(defun quick-view-file-at-point ()
  "Preview the file at point then jump back after some idle time.

In order for this to work you need to bind this function to a key combo, 
you cannot call it from the minibuffer and let it work.

The reason it works is that by holding the key combo down, you inhibit
idle timers from running so as long as you hold the key combo, the 
buffer preview will still display."
  (interactive)
  (let* ((buffer (current-buffer))
         (file (thing-at-point 'filename t))
         (file-buffer-name (format "*preview of %s*" file)))
    (if (and file (file-exists-p file))
        (let ((contents))
          (if (get-buffer file)
              (setq contents (save-excursion
                               (with-current-buffer (get-buffer file)
                                 (font-lock-fontify-buffer)
                                 (buffer-substring (point-min) (point-max)))))
            (let ((new-buffer (find-file-noselect file)))
              (with-current-buffer new-buffer
                (font-lock-mode t)
                (font-lock-fontify-buffer)
                (setq contents (buffer-substring (point-min) (point-max))))
              (kill-buffer new-buffer)))
          (switch-to-buffer (get-buffer-create file-buffer-name))
          (setq-local header-line-format "%60b")
          (delete-region (point-min) (point-max))
          (save-excursion (insert contents))
          (local-set-key (kbd "C-M-v") (lambda () (interactive) (sit-for .2)))
          (run-with-idle-timer
           .7 
           nil
           (lambda ()
             (switch-to-buffer buffer)
             (kill-buffer file-buffer-name))))
      (message "no file to preview at point!"))))

Também aqui está um gif dele em ação, tudo o que faço é:

  • coloque meu cursor sobre o arquivo
  • pressione e segure minha tecla
  • a visualização é exibida
  • quando eu solto, a visualização é interrompida e você volta para onde estava.

insira a descrição da imagem aqui

Uma coisa importante a observar são os segundos do temporizador inativo, no meu código que usei, .7mas é um número mágico, você deseja mantê-lo muito pequeno, mas se a visualização piscar duas vezes, tente aumentá-lo 1/10 por segundo a cada vez até encontrar o local certo para sua máquina.

* Observe também que, na função, tento fazer alguma fonte do buffer de visualização, mas não consegui fazê-lo funcionar, esse será o próximo passo para torná-lo mais útil. **

Jordon Biondo
fonte
Agradável! Isso é o tipo de coisa que precisamos ver aqui.
Malabarba 28/09
Eu recebo um Error running timer: (void-variable buffer)com isso, parece que o buffervar não está disponível dentro do run-with-idle-timer?
Lee H
Verifique se a ligação lexical é t
Jordon Biondo 23/10
Você pode repetir esta resposta por lá .
Malabarba 27/10/2014
8

Conforme apontado nos comentários, as funções são vinculadas a chaves, não a eventos. Mas, para dar um passo atrás, não sei se entendi por que é importante manter a tecla pressionada enquanto você (presumivelmente) está lendo o conteúdo do arquivo. Também seria incompatível com ações básicas (e razoáveis), como rolagem, para obter mais informações. Sem mencionar o fato de que, se demorar um pouco, pode ficar desconfortável :)

Que tal repetir uma chave? Algo como o seguinte pode ser o esqueleto básico de um equivalente funcional:

(defun my-dired-view-file ()
  (interactive)
  (dired-view-file)
  (local-set-key (kbd "<f5>") 'View-quit))

(define-key dired-mode-map (kbd "<f5>") 'my-dired-view-file)

Enfim, eu sou mais desafiador no seu caso de uso do que em responder à sua pergunta neste momento, pois isso não tem nada a ver com ligações de pressionar / pressionar :)

Sigma
fonte
Estou imaginando uma longa lista de arquivos em dired. Não sei qual é o conteúdo de cada um dos arquivos. se eu pudesse visualizar o F5, deixe o F5 parar de visualizar e voltar ao direcionamento e continue com o próximo candidato etc. Não acho que você tenha desmentido meu caso de uso, mas pode ter sugerido uma boa alternativa com base pressionando F5 novamente para parar a visualização.
Eric Brown
o que você sugere é comparável com a funcionalidade em Midnight Commander (F3)
Eric Brown
1
A resposta enviada por @Sigma é interessante. Porém, ao navegar em um diretório usando dired, você já pode pressionar v para visualizar o arquivo e, ao visualizar esse arquivo, pressione q para sair e retornar ao diretório. Eu acho que pressionar a mesma tecla para visualizar e sair é mais fácil.
Nsukami _
@LeMeteore obrigado por me lembrar dired-view-file! Eu editei meu código para aproveitá-lo. Sim, acho que nesse tipo de cenário, não é necessário mudar para uma chave diferente.
Sigma
4

Em vez de mostrar o arquivo enquanto uma tecla é pressionada, o que seria muito difícil de implementar, sugiro mostrar o arquivo até a próxima tecla ser pressionada.

(defun dired-find-file-until-key ()
  (interactive)
  (let ((filename (dired-file-name-at-point))
    (buffer-count (length (buffer-list))))
    (dired-find-file)
    (message "Showing %s temporarily..." filename)
    (isearch-unread-key-sequence (list (read-event)))
    (if (= (length (buffer-list)) buffer-count)
    (bury-buffer)
      (kill-buffer))))

Aqui está uma variante que mostra o arquivo em outra janela, que eu acho que é uma interface de usuário mais conveniente.

(defun dired-find-file-other-window-until-key ()
  (interactive)
  (let ((buffer-count (length (buffer-list))))
    (dired-find-file-other-window)
    (isearch-unread-key-sequence (list (read-event)))
    (if (= (length (buffer-list)) buffer-count)
    (delete-window)
      (kill-buffer-and-window))))

Você não poderá fazer mais do que rolar no buffer. Pode fazer mais sentido implementar um modo de "visualização rápida" em que os comandos de rolagem são aceitos, mas outros eventos de entrada fazem com que o modo de visualização rápida saia e são interpretados de acordo com o modo anterior, como o Isearch.

Com v( dired-view-file), você obtém algo intermediário: o buffer é editado no modo Exibir , onde você pode rolar, pesquisar etc. etc., mas fechar o buffer é o pressionamento de tecla simples q.

Gilles 'SO- parar de ser mau'
fonte
2

Outra possibilidade, se você usar um mouse, é colocar a visualização desejada em uma dica de ferramenta . Então, quando você move o mouse sobre um nome de arquivo (com propriedade help-echo), a visualização será exibida.

Eu uso essa técnica no Dired + , por exemplo, para (opcionalmente) mostrar visualizações das imagens associadas aos arquivos de imagem, quando você passa o mouse sobre os nomes dos arquivos.

Você pode ver o efeito disso fazendo isso após o carregamento dired+.el:

  • Certifique-se que tooltip-modeestá ligado: (tooltip-mode 1).

  • Verifique se a opção não diredp-image-preview-in-tooltippossui nilvalor (o tamanho da miniatura ou fulluma imagem em tamanho real).

  • Coloque o ponteiro do mouse sobre um nome de arquivo de imagem em Dired.

Você pode usar o código de função diredp-mouseover-helpcomo inspiração para fazer o que deseja (exiba sua "visualização rápida" na passagem do mouse). Veja as chamadas dessa função para saber como usá-la. Aqui está uma dessas chamadas:

 (add-text-properties (line-beginning-position) (line-end-position)
                      '(mouse-face highlight help-echo diredp-mouseover-help))
Desenhou
fonte
Você me perdeu em "se você usa um mouse". ;-) Isso não está funcionando para mim. image-diredfunciona bem, mas tudo que eu vejo quando eu mouse sobre émouse-1: visit this file/dir in another window
nispio
Você não verá o que eu disse se não carregar dired+.ele seguir as outras instruções que eu dei. Não é um recurso Emacs de baunilha. Eu estava tentando descrever como você pode rolar seu próprio código para fazer o que quiser. O dired+.elcódigo está muito próximo, eu acho, do que você diz que quer. Mas sim, as dicas de ferramentas do mouse exigem que você use um mouse. Caso contrário, a sugestão de usar uma dica de ferramenta não ajudará muito. ;-)
Drew
Entendo como carregar pacotes e seguir as instruções, mas não está funcionando para mim. Não sei como retomar essa conversa no chat, mas talvez devêssemos fazer isso.
Nispio 26/09/14
1

A partir de um buffer direcionado, vvisitará um arquivo no modo somente visualização e qencerrará o modo de exibição e o levará de volta ao buffer direcionado. Essa é uma maneira rápida de visualizar um arquivo e oferece a possibilidade de rolar e até pesquisar no buffer.

Não acho que o emacs tenha a capacidade de transmitir mensagens de baixo nível de teclas que recebe do sistema operacional. Isso pode ser parcialmente por razões históricas. Os terminais disponíveis para hackers (leia-se "programadores") na época em que o emacs estava sendo desenvolvido nas décadas de 1970 a 1980 não funcionavam com eventos de ativação / desativação de chaves em tempo real, mas com uma simples entrada de caracteres e seqüências de escape. Até hoje, o emacs ainda pode operar de maneira impressionante nos limites de uma sessão simples de terminal ou SSH usando apenas caracteres ASCII simples e seqüências de escape.

Isso não quer dizer que a funcionalidade não tenha aumentado significativamente ao longo dos anos para incluir recursos como menus, gerenciamento de vários quadros e interação com o mouse. Não há razão (que eu saiba) de que o emacs não possa ser alterado (em sua essência) para disponibilizar mensagens-chave de baixo nível para extensões, mas eu não prenderia a respiração.

( Isenção de responsabilidade: este post deve ser tomado como opinião e especulação, e não como fato difícil.)

nispio
fonte
1

Eu dei a minha solução nesta questão SO /programming/26409768/how-to-show-buffer-content-in-real-time-in-other-window-when-focus-is-in- amortecedor

e minha resposta é alterar o comportamento das teclas de navegação ne pmostrar o arquivo em outro ponto da janela. O foco permanece no buffer direcionado e matamos o buffer visitado quando continuamos navegando.

Criei um modo secundário para ativar / desativar esse recurso facilmente. Observe que ainda temos as teclas de setas para a navegação «normal». Ligue M-x dired-show-mode(ou ranger-modeporque esse é um recurso que eu descobri no gerenciador de arquivos da guarda florestal ).

O código: (qualquer revisão e relatório de bug apreciado!) Https://gitlab.com/emacs-stuff/my-elisp/blob/master/dired-show.el

(defgroup dired-show nil
  "See the file at point when browsing in a Dired buffer."
  :group 'dired
  )

(setq show-next-current-buffer nil)

(defun show-next ()
     (interactive)
     (next-line 1)
     (dired-find-file-other-window)
     (if show-next-current-buffer (kill-buffer show-next-current-buffer))
     (setq show-next-current-buffer (current-buffer))
     (other-window 1)
     )

(defun show-previous ()
     (interactive)
     (previous-line 1)
     (dired-find-file-other-window)
     (if show-next-current-buffer (kill-buffer show-next-current-buffer))
     (setq show-next-current-buffer (current-buffer))
     (other-window 1)
     )


(define-minor-mode dired-show-mode
  "Toggle preview of files when browsing in a Dired buffer."
  :global t
  :group 'dired-show
  (if dired-show-mode
      (progn
        (define-key dired-mode-map "n" 'show-next)
        (define-key dired-mode-map "p" 'show-previous)
        )
  (define-key dired-mode-map "n" 'diredp-next-line)
  (define-key dired-mode-map "p" 'diredp-previous-line)
  ))

(defalias 'ranger-mode 'dired-show-mode)

(provide 'dired-show)
;;; dired-show ends here
Ehvince
fonte
0

Você precisaria pesquisar a fila de eventos até que um evento diferente, ou nenhum, fosse lido. A carga da CPU é perceptível, embora razoavelmente baixa.

(defun dired-preview-command ()
  (interactive)
  (let* ((file (or (dired-get-filename nil t)
                   (error "No file here")))
         (visited-p (get-file-buffer file))
         (buffer (or visited-p (find-file-noselect file)))
         (window
          (display-buffer buffer '(nil . ((inhibit-same-window . t)))))
         (event (read-event)))
    (while (and event (eq last-command-event event))
      (setq event (read-event nil nil 0.1)))
    (when event
      (setq unread-command-events
            (list event)))
    (quit-window (not visited-p) window)))
politza
fonte