Como exibir um buffer de ajuda / tamanho de quadro completo da janela (não em tela cheia)

8

Às vezes, quero exibir informações no estilo de buffer da Ajuda, portanto, tenho usado códigos como este:

(with-help-window (help-buffer)
  (princ "Type q to exit this help buffer.\n\n")
  (princ result))

Isso funciona bem, mas a janela de ajuda usa apenas metade do meu quadro. Normalmente, divido minha moldura horizontalmente, para dar duas janelas altas. O buffer de ajuda exibido usa uma das duas janelas.

Prefiro usar o quadro inteiro em alguns casos, para exibir mais informações e reduzir o número de vezes que preciso percorrer as informações exibidas. O problema a ser resolvido é como usar temporariamente o quadro inteiro para a with-help-windowchamada e restaurar automaticamente os tamanhos dos buffers / janelas originais quando digito "q" na janela de ajuda.

Como posso alcançar melhor esse objetivo? Acho que estou procurando algo assim:

(with-FULL-FRAME-help-window (help-buffer)
   ...)

Examinei o modo vencedor, marcadores, salvando layouts em registros, os vários (display-buffer ...)métodos (e poderosos, mas complexos) . A maioria deles parece um pouco fora do alvo para minha intenção desejada, porque eles tendem a corrigir / restaurar um layout após uma operação de exibição de quadro completo. E parece-me que muitos deles exigem que eu restaure manualmente meu layout de janela (o que eu preferiria não fazer).

Gostaria de saber se alguém já ouviu falar de uma maneira de resolver isso simplesmente. Espero algo simples como essas possíveis abordagens, onde eu possa substituir algo com um quadro let ...

(let ((help-window-width-display-option fullwidth))
  (with-help-window (help-buffer)
    ...))

Ou esse tipo de abordagem, que ainda não sei fazer, e que parece um pouco difícil / complicado para o meu nível de habilidade atual.

(let ((save original configuration somehow)
  (delete-other-windows)
  (with-help-window (help-buffer)
     ...)
  ;; somehow, when I type "q" in the help buffer
  ;; - catch that action in code after the buffer is killed
  ;; - and restore the original window configuration
  )

Parece-me que o principal problema para resolver é como restaurar automaticamente a configuração original da janela quando digito "q" no buffer temporário do modo de ajuda. obrigado

Kevin
fonte
Uma idéia seria usar display-buffer-pop-up-frame: gnu.org/software/emacs/manual/html_node/elisp/… Outra idéia seria emitir um make-frame tempo usando display-bufferuma função personalizada para atingir esse novo quadro. Se você estiver interessado em localizar e direcionar um quadro existente, dê uma olhada neste exemplo: stackoverflow.com/questions/18346785/…
lawlist
Aqui está uma idéia de como salvar e restaurar a configuração janela para que você pode usar a estrutura existente: emacs.stackexchange.com/a/2714/2287 Se você achar que como como determinadas configurações de janela, você pode querer considerar a criação algo mais elaborado - existem várias bibliotecas que tratam de salvar e alternar entre várias configurações de janelas.
lawlist
Como de costume, obrigado por sua ajuda. Eu já tentei display-buffer-pop-up-frame, pois é bem próximo do que procuro. Mas ... o quadro aparece em outro lugar (não o meu quadro atual), e devo enviá-lo com cmd-w, não "q" no estilo de ajuda. Salvar / restaurar configurações de janela não é o problema subjacente. Atualmente, estou inclinado a clonar e modificar a fonte do with-help-window para oferecer uma opção que eu possa deixar vincular ou encerrar com um defmacro ou algo assim. Eu sorrio para o quão exigente nós emacs as pessoas estão querendo exatamente o que queremos do Emacs.
Kevin
Depois de ler mais em help.el, a solução parece estar enterrado em algum lugar help-return-method, quit-windowo quit-restoreparâmetro janela, e provavelmente algum código personalizado para definir / usar todas essas coisas para criar o efeito desejado.
Kevin

Respostas:

5

Exemplo # 1 : O atalho de teclado qno help-modebuffer vem do special-mode-mapque é incorporado ao help-mode-map. O valor padrão é quit-window, que oferece apenas quatro (4) ações possíveis: " De acordo com as informações armazenadas no quit-restoreparâmetro da janela do WINDOW (1) exclua o WINDOW e seu quadro, (2) exclua o WINDOW, (3) restaure o buffer exibido anteriormente no WINDOW ou (4) faça com que o WINDOW exiba outro buffer que não o atual. Se não for nulo, redefina o quit-restoreparâmetro para nulo. "[Consulte a string de documentos: M-x describe-function RET quit-window RET]

Aqui está um resumo do que este exemplo faz:

  • Deixe vincular a variável help-window-selectpara tque a *Help*janela seja selecionada.

  • Deixe-vincular a configuração atual da janela a uma variável temporária chamada config.

  • Gere a *Help*janela.

  • Armazene a configuração da janela anterior - config- em uma variável local chamada my-stored-win-config.

  • Crie uma atribuição de chave local para a letra à qqual está vinculada my-restore-win-config. [Esta tarefa local supera / oculta a tarefa anterior de quit-window.]

  • Exclua outras janelas.

  • Pressione a letra qpara restaurar a configuração anterior da janela e interrompa o *Help*buffer.

(defvar my-stored-win-config nil)
(make-variable-buffer-local 'my-stored-win-config)

(defun my-restore-win-config ()
  (interactive)
  (when my-stored-win-config
    (set-window-configuration my-stored-win-config)
    (kill-buffer "*Help*")))

O fragmento a seguir é um exemplo de uso, mas não é uma função interativa completa. Pode ser avaliado no *scratch*buffer para vê-lo em ação.

(let ((help-window-select t)
      (config (current-window-configuration)))
  (with-help-window (help-buffer)
    (princ "Type q to kill this *Help* buffer and restore prior window configuration."))
  (with-current-buffer "*Help*"
    (setq my-stored-win-config config)
    (local-set-key "q" 'my-restore-win-config))
  (delete-other-windows))

Exemplo 2 :

Aqui está uma macro independente que faz tudo como o exemplo acima, que lida com três situações possíveis relacionadas aos valores de gancho existentes - por exemplo nil, símbolo ou lista de símbolos.

(defmacro help-window-full-frame (buffer-name &rest body)
"Doc-string."
  (declare (indent 1) (debug t))
  `(progn
    (set-marker help-window-point-marker nil)
      (let* (
          (help-window-select t)
          (foo
            (lambda ()
              (set (make-local-variable 'window-configuration)
                (current-window-configuration))
              (local-set-key "q"
                (lambda ()
                  (interactive)
                  (when window-configuration
                    ;; Record the `current-buffer' before it gets buried.
                    (let ((cb (current-buffer)))
                      (set-window-configuration window-configuration)
                      (kill-buffer cb)))))))
          ;; Preserve the original hook values by let-binding them in advance.
          ;; Otherwise, `add-to-list' would alter the global value.
          (temp-buffer-window-setup-hook temp-buffer-window-setup-hook)
          (temp-buffer-window-show-hook temp-buffer-window-show-hook)
          (temp-buffer-window-setup-hook
            (cond
              ((null temp-buffer-window-setup-hook)
                (list 'help-mode-setup foo))
              ((and
                  (not (null temp-buffer-window-setup-hook))
                  (listp temp-buffer-window-setup-hook))
                (add-to-list 'temp-buffer-window-setup-hook foo)
                (add-to-list 'temp-buffer-window-setup-hook 'help-mode-setup))
              ((and
                  (not (null temp-buffer-window-setup-hook))
                  (symbolp temp-buffer-window-setup-hook))
                (list 'help-mode-setup foo temp-buffer-window-setup-hook))))
          (temp-buffer-window-show-hook
            (cond
              ((null temp-buffer-window-show-hook)
                (list 'help-mode-finish 'delete-other-windows))
              ((and
                  (not (null temp-buffer-window-show-hook))
                  (listp temp-buffer-window-show-hook))
                (add-to-list 'temp-buffer-window-show-hook 'delete-other-windows)
                (add-to-list 'temp-buffer-window-show-hook 'help-mode-finish))
              ((and
                  (not (null temp-buffer-window-show-hook))
                  (symbolp temp-buffer-window-show-hook))
                (list
                  'help-mode-finish
                  'delete-other-windows
                  temp-buffer-window-show-hook)))) )
        (with-temp-buffer-window ,buffer-name nil 'help-window-setup (progn ,@body)))))

E aqui está o trecho de amostra para avaliar no *scratch*buffer.

(help-window-full-frame (help-buffer)
  (princ "Type q to kill this *Help* buffer and restore prior window configuration."))
lista de leis
fonte
Uau, obrigado por uma excelente resposta. Eu progredi para salvar / restaurar a configuração da janela e criei uma my-help-quitfunção enquanto tentava religar a chave do mapa de ajuda dentro de with-help-window. Mas não estava funcionando. Agora vejo que você vincula a chave dentro do buffer da Ajuda (não da janela da Ajuda como eu estava fazendo) após a instalação do buffer. Eu acho que minha ligação foi derrotada pela configuração do buffer. Uma lição aprendida. Tudo está funcionando agora. Muito Obrigado.
Kevin
Existem duas (2) oportunidades para agir diretamente sobre o *Help*buffer antes que ele termine - o temp-buffer-window-setup-hookque é executado help-mode-setupe, em seguida, qualquer outra coisa já / previamente atribuída ao gancho; e, em seguida, o temp-buffer-window-show-hookque é executado help-mode-finishe qualquer coisa já atribuída anteriormente ao gancho. help-mode-setupdeve permanecer primeiro, mas você pode adicionar algo por trás disso vinculando qualquer um desses ganchos acima mencionados com itens personalizados. Nesse cenário, você não precisaria with-current-buffer.
lawlist
Acordado. Eu olhei para os dois help-mode-setupe help-mode-finish, mas ambos correram antes que o buffer fosse exibido. O principal problema foi redirecionar a combinação de teclas "q" e você me mostrou como fazer isso no buffer (não na janela, o que eu estava tentando fazer). PS. Tentei escrever uma solução como (defmacro with-full-frame-help-window, mas a macro ainda requer uma função separada para lidar com a ação de restauração "q" e janela. Vou postar minhas funções concluídas abaixo.
21716 Kevin
Atualizei a resposta com um segundo exemplo que usa uma macro independente que faz tudo o que o primeiro exemplo faz.
lawlist
11
Isso também funciona para mim, para substituir a referência do buffer " Help " codificada no buffer atual, porque a restauração lambda é uma função local do buffer. ... (kill-buffer (current-buffer)))))). A macro tomou um nome de buffer como argumento e eliminou " Help ", para que houvesse um problema se o chamador usasse um buffer cujo nome fosse diferente. buffer-nameModifiquei minha macro para remover o parâmetro e gerou / eliminou o mesmo buffer dentro do defmacro.
21716 Kevin
3

Com base na excelente resposta do @lawlist, aqui estão minhas funções completas para o próximo cara ...

;; a tmp buffer-local place that gets destroyed with the help buffer
(defvar kwj-v-window-config-saved nil)
(make-variable-buffer-local 'kwj-v-window-config-saved)

(defun kwj-help-window-full-frame (string)
  "Show STRING in a help buffer using the full current frame."
  (let (original-layout)
    ;; set this before Help changes the config
    (setq original-layout (current-window-configuration))
    (with-help-window (help-buffer)
      (princ "Type q to exit this help buffer.\n\n")
      (princ string))
    (with-current-buffer "*Help*"
      ;; save layout in buffer local var that gets deleted
      (setq kwj-v-window-config-saved original-layout)
      ;; bind key in BUFFER (not in help window above)
      ;; bind key *after* help buf is displayed
      (local-set-key "q" 'kwj-help-window-restore))
    (delete-other-windows)))

(defun kwj-help-window-restore ()
  "Restore original windows after a full frame help display."
  (interactive)
  (set-window-configuration kwj-v-window-config-saved)
  (kill-buffer "*Help*"))

A longa cadeia de comentários acima, com a ajuda contínua do @lawlist, resultou nesta versão de uma macro que não requer um nome de buffer, trata adequadamente a instalação original / mostra as listas de ganchos e não causa problemas com o "q "em outros buffers do modo Ajuda .

(defmacro with-help-window-full-frame (&rest body)
  "Display text in a full-frame help window.
Execute BODY forms to put output into the window, with standard
output directed to the buffer."
  ;;tell indenter about this macro name
  (declare (indent 1))
  ;; must use a buffer string name here, not the buffer itself
  `(let ((mybuf ,(buffer-name (get-buffer-create "Full Frame Help")))
         ;;`(let ((mybuf ,(help-buffer))
         mysetup tmpsetup tmpshow)
     ;; save a copy of original hooks
     (setq tmpsetup (copy-list temp-buffer-window-setup-hook))
     (setq tmpshow (copy-list temp-buffer-window-show-hook))

     ;; create window config store and restore functions
     ;; credit to @lawlist on stackoverflow for this embedded setup
     (setq mysetup
           (lambda ()
             ;; store original window configuration
             (set (make-local-variable 'orig-win-config)
                  (current-window-configuration))
             ;; bind q to the window restore function
             (local-set-key
              "q"
              (lambda ()
                (interactive)
                ;; q is shared by all Help-mode buffers
                ;; so guard those that did not set up orig-win-config
                (when (boundp 'orig-win-config)
                  (set-window-configuration orig-win-config))
                (kill-buffer (current-buffer))))))

     ;; Add to help setup hooks. Keep original hook functions if any
     ;; delete-dups destructively hacks our tmp copy, not original hooklists
     (push mysetup tmpsetup)          ;order critical here
     (push 'help-mode-setup tmpsetup) ;this must be first in hook
     (delete-dups tmpsetup)

     (push 'help-mode-finish tmpshow) ;order not important here
     (push 'delete-other-windows tmpshow)
     (delete-dups tmpshow)

     ;; shadow the original hooks with our copies for the display call
     (let ((temp-buffer-window-setup-hook tmpsetup)
           (temp-buffer-window-show-hook tmpshow))

       ;; show buf with locally embedded window restore function
       (with-temp-buffer-window mybuf nil
                                'help-window-setup
                                (progn ,@body)))))

Use a macro desta maneira:

(with-help-window-full-frame
    (princ "Type q to exit this buffer."))
Kevin
fonte