Emacs Pinkyを避ける方法:hydra-pinky


私の Emacs設定 は、プログラマー masasamさんのブログ「 Solist Work Blog」から多くのことを吸収して日々育てています。そのブログの中にあるEmacs Pinkyをhydraで解決する の記事を参考にして更に使いやすくカスタマイズ設定してみました。hydra-pinkyを使い出すとその快適さにはまります。

Screen Shot

hydra-pinky を発動するとミニバッファーに赤文字のキーメニューがでてきます。 これらの赤い表示のキーをタイプしている間はいつまでたってもhydraは解除されません。hydraが終了する条件は、定義された赤いキー以外のキーをタイプするか、青文字の "q":quit を押した場合です。

hydra-pinkyは、vew-modeに似たコンセプトの動作をし、そこから抜けると普通の編集モードに戻る…という仕組みです。キーバインドを覚える必要もなくGUIでスピーディーにキー操作できるのはビギナーEmacserにとってはとてもありがたいです。私はhydra-pinkyの他にもいろいろhydraを活用しています。

HydraでEmacsのキーバインド問題を解消

sequential-command

rubikitch/sequential-command

Emacsを再起動して、C-a C-a C-aすると、行頭にいって、バッファーの頭にいって、元に戻り、C-e C-e C-eすると行末にいって、バッファーの最後尾にいって、元に戻るというシンプルな機能ですが、なにげに便利です。

hydra-pinkyでは、"a" , "e" キーに割り当てています。

window-toggle-division

Windowの縦分割、横分割をtoggleで切り替えします。

iflipb:バッファー移動

バッファー移動は、next-buffer previous-buffer を使ってもいいのですが、不要なbufferをignoreできるiflipbを使うとよりスマートに使えます。
Emacs:タブを使わない究極のバッファー移動

矢印キーの扱い

Emacserの方から見ると邪道だと言われそうですが、私はカーソル移動に矢印キーを使うことも多いです。基本は、h,j,k,lを使うようにしていてもうっかり矢印キーに触れるとhydra-pinkyが消えてしまうので、矢印関係の操作でpinkyが消えないようにしています。

トラックパッドを無効にする

私の場合、Macbookを使っているのでhydra-pinky発動中にうっかりトラックパッドに触れると勝手に解除されてしまいます。そこで、マウスを使うときはトラックパッドを無効にする設定をしています。
MacBookのトラックパッドを無効にする

設定

(bind-key [f11] 'hydra-pinky/body)
(key-chord-define-global
 "::"
 (defhydra hydra-pinky (:color red :hint nil)
   "
 :_0_._1_._2_._3_._o_._S_._x_   :_j_._k_._h_._l_._c_._a_._e_._b_._SPC_._m_._w_._s_._/_   :_n_._p_._u_._t_   :_<_-_:_-_>_   :_q_uit"
   ;; window
   ("0" delete-window)
   ("1" delete-other-windows)
   ("2" split-window-below)
   ("3" split-window-right)
   ("o" other-window-or-split)
   ("S" window-swap-states)
   ("x" window-toggle-division)
   ;; page
   ("a" seq-home)
   ("e" seq-end)
   ("j" next-line)
   ("k" previous-line)
   ("l" forward-char)
   ("h" backward-char)
   ("c" recenter-top-bottom)
   ("<down>" next-line)
   ("<up>" previous-line)
   ("<right>" forward-char)
   ("<left>" backward-char)
   ("<C-up>" backward-paragraph)
   ("<C-down>" forward-paragraph)
   ("<C-left>" left-word)
   ("<C-right>" right-word)
   ("b" scroll-down-command)
   ("SPC" scroll-up-command)
   ("m" set-mark-command)
   ("w" avy-goto-word-1)
   ("s" swiper-isearch-region)
   ;; git
   ("n" git-gutter:next-hunk)
   ("p" git-gutter:previous-hunk)
   ("u" git-gutter:popup-hunk)
   ("t" git-gutter:toggle-popup-hunk)
   ;; buffer
   ("/" kill-buffer)
   (":" counsel-switch-buffer)
   ("<" iflipb-previous-buffer)
   (">" iflipb-next-buffer)
   ;; quit
   ("q" nil)))

;; sequential-command
(use-package sequential-command-config
  :commands sequential-command-setup-keys
  :hook (after-init . sequential-command-setup-keys))

;; other-window-or-split
(bind-key
 "C-q"
 (defun other-window-or-split ()
   "If there is one window, open split window.
If there are two or more windows, it will go to another window."
   (interactive)
   (when (one-window-p)
     (split-window-horizontally))
   (other-window 1)))

;; window-toggle-division
(defun window-toggle-division ()
  "Replace vertical <-> horizontal when divided into two."
  (interactive)
  (unless (= (count-windows 1) 2)
    (error "Not divided into two!"))
  (let ((before-height)
        (other-buf (window-buffer (next-window))))
    (setq before-height (window-height))
    (delete-other-windows)
    (if (= (window-height) before-height)
        (split-window-vertically)
      (split-window-horizontally))
    (other-window 1)
    (switch-to-buffer other-buf)
    (other-window -1)))

;; iflipb
(setq iflipb-wrap-around t)
(setq iflipb-ignore-buffers (list "^[*]" "^magit" "dir]$"))
;; sequential-command
(use-package sequential-command-config
  :commands sequential-command-setup-keys
  :hook (after-init . sequential-command-setup-keys))