Ivy 후보들을 window에 표시하기

ivy의 후보들은 보통 minibuffer에 표시되는데 그럼 미니버퍼가 나올 때마다 프레임 전체의 글자가 움직이므로 가능한한 다른 파트의 움직임이 적어지게 독립적인 window에 표시하려 한다. ivy-posframe을 사용하면 해결되나 posframe이 아래 창을 가리게 되어 swiper같이 candidates와 원본을 같이 봐야하는 상황에서는 곤란해진다. 그래서 posframe도 아닌 minibuffer도 아닌 window에서 candidates를 표시한다. 이 해법은 ivy wiki에 있는 것을 가져와서 일부를 고쳤다.

(use-package ivy
  :bind
  (("s-r" . ivy-resume)
   :map ivy-minibuffer-map
   ("<escape>" . minibuffer-keyboard-quit))
  :config
  (defun ivy-display-function-window (text)
    (let ((buffer (get-buffer-create "*ivy-candidate-window*"))
	  (str (with-current-buffer (get-buffer-create " *Minibuf-1*")
		 (let ((point (point))
		       (string (concat (buffer-string) "  " text)))
		   (ivy-add-face-text-property
		    (- point 1) point 'ivy-cursor string t)
		   string))))
      (with-current-buffer buffer
	(let ((inhibit-read-only t))
	  (setq truncate-lines t) ; 긴 candidate가 다음 줄로 넘어가지 않게 한다
	  (erase-buffer)
	  (insert str)
	  (goto-char (point-min)))) ; 선택된 candidate가 화면에 보이게 한다
      (with-ivy-window
	(display-buffer
	 buffer
	 `((display-buffer-reuse-window
	    display-buffer-below-selected)
	   (window-height . ,(1+ (ivy--height (ivy-state-caller ivy-last))))
	   (window-parameters . ((header-line-format . none)
				 (mode-line-format . none))))))))

  (setq ivy-use-virtual-buffers t
	ivy-height 15
	ivy-display-functions-alist '((swiper . ivy-display-function-window)
				      (counsel-rg . ivy-display-function-window)
				      (ivy-switch-buffer . ivy-display-function-window)
				      (counsel-find-file . ivy-display-function-window)
				      (t . ivy-display-function-window)))
  (ivy-mode 1))

댓글

Comments powered by Disqus