HydraでEmacsのキーバインド問題を解消する
できるだけデフォルトを上書きしないようにと配慮しながらEmacsのキーバインドを考えるとなるとなかなか難しいですね。うまく割り当てできたとしてもとても覚えて使いこなすのは至難です。その問題を解消して視覚的で使いやすいUIを提供してくれるのが Hydra
です。
Hydra
はとても奥が深くまだまだ使いこなせないのですが、勉強を兼ねていろいろ設定しましたので備忘録を兼ねてご紹介します。こうすればなお良い…というようなアドバイスを頂けると嬉しいです。
設定の大部分は、hydraの作者であるabo-abo氏のTipsを参考にしました。
Hydra-melpa
emacsのパッケージ管理はいろいろあるようですが、私はMelpaを利用して、必要なパッケージは、init.el に書いて自動インストールされるようにしているのですが、メンテナンス(package-install、update、remove) のためのコマンドをhydraで設定しています。
M-x package-list-packege
でリストを表示させてもいいのですが “U” で update
すると全てが対象になって思わぬトラブルに遭遇することもあるので、package-utils
というパッケージを使っています。
;; use package-utils.el
(defhydra hydra-melpa (:color red :hint nil)
"
Package: _u_pdate _r_emove _i_nstall"
("u" package-utils-upgrade-by-name)
("r" package-utils-remove-by-name)
("i" package-install))
Hydra-git-gutter
emacsの設定ファイル群は、Gitで管理していますので、magit
は必要不可欠です。
編集中は、git-gutterが便利なのでまとめてhydraに設定しています。
;; 02_git.el --- 02_git.el
;;; Commentary:
;;; Code:
;; (setq debug-on-error t)
;; magit
(autoload 'magit-status "magit" nil t)
(defadvice magit-status (around magit-fullscreen activate)
"Magit-status always in fullr screen."
(window-configuration-to-register :magit-fullscreen)
ad-do-it
(delete-other-windows))
(bind-key [f8] 'magit-status)
;; git-gutter
(global-git-gutter-mode t)
(defun git-gutter:toggle-popup-hunk ()
"Toggle git-gutter hunk window."
(interactive)
(if (window-live-p (git-gutter:popup-buffer-window))
(delete-window (git-gutter:popup-buffer-window))
(git-gutter:popup-hunk)))
;; Hydra
(bind-key
"s-g"
(defhydra hydra-git-gutter (:color red :hint nil)
"
_m_agit _b_lame _d_ispatch _t_imemachine | hunk: _p_revious _n_ext _s_tage _r_evert pop_u_p _SPC_:toggle"
("m" magit-status :exit t)
("b" magit-blame :exit t)
("t" git-timemachine :exit t)
("d" magit-dispatch :exit t)
("p" git-gutter:previous-hunk)
("n" git-gutter:next-hunk)
("s" git-gutter:stage-hunk)
("r" git-gutter:revert-hunk)
("u" git-gutter:popup-hunk)
("SPC" git-gutter:toggle-popup-hunk)))
;; Local Variables:
;; byte-compile-warnings: (not free-vars callargs)
;; End:
;;; 02_git.el ends here
Hydra-counsel
私のemacsの補完インターフェイスは、脱Helmにこだわっています。
counselはとても優秀で便利なのですがキーバインドが覚えられないのでhydraにしました。頻繁に使うオーソドックなものは別にキーバインドするので、hydraからは除外しています。
;;; 05_counsel.el --- 05_counsel.el
;;; Commentary:
;;; Code:
;; (setq debug-on-error t)
(ivy-mode 1)
(setq ivy-use-virtual-buffers t)
(setq ivy-use-selectable-prompt t)
(setq enable-recursive-minibuffers t)
(bind-key "M-:" 'ivy-switch-buffer)
(bind-key "M-s" 'swiper-for-region-or-swiper)
(bind-key "C-s" 'swiper-migemo)
(bind-key "M-x" 'counsel-M-x)
(bind-key "C-x C-f" 'counsel-find-file)
;; hydra-counsel
(bind-key
"C-/"
(defhydra hydra-counsel (:hint nil :exit t)
"
Counsel: describ-_f_unction _i_nfo-lookup-symbol _d_iscbinds _y_ank-pop _l_ocate _a_g
describ-_v_ariable find-_L_ibrary _u_nicode-char _m_ark-ring _g_it-grep _r_g"
("d" counsel-descbinds)
("y" counsel-yank-pop)
("m" counsel-mark-ring)
("f" counsel-describe-function)
("v" counsel-describe-variable)
("L" counsel-find-library)
("i" counsel-info-lookup-symbol)
("u" counsel-unicode-char)
("g" counsel-git-grep)
("i" counsel-git)
("a" counsel-ag)
("r" counsel-rg)
("l" counsel-locate)))
;; swiper-for-region-or-swiper
(defun swiper-for-region-or-swiper ()
"If the region is active, swiper-for-region.
If the region is inactive, swiper."
(interactive)
(if (region-active-p)
(swiper (buffer-substring
(region-beginning) (region-end)))
(swiper)))
;; swiper-migemo
(use-package avy-migemo-e.g.swiper)
(defun swiper-migemo ()
"Using migemo with Swiper."
(interactive)
(avy-migemo-mode 1)
(swiper)
(avy-migemo-mode 0))
;; counsel-tramp
(setq tramp-default-method "ssh")
;; Local Variables:
;; byte-compile-warnings: (not free-vars callargs)
;; End:
;;; 05_counsel.el ends here
Hydra-dired
diredのキーバインドはよく使うのですぐに覚えますから、あえてhydraにこだわることもないでしょう。お気に入りのデレクトリを一発で開いたり、trampを起動させたり、macアプリのfinder.app(ファイラー)や iterm(ターミナルアプリ)を起動させたりというショートカット機能も加えて遊んでみました。
dired-modeから “.” でtoggle表示させているところが味噌です。
;;; 30_dired.el --- 30_dired.el
;;; Commentary:
;;; Code:
;; (setq debug-on-error t)
;; Dired files deleted by trash and no ask recursive
(setq delete-by-moving-to-trash t
dired-recursive-copies 'always
dired-recursive-deletes 'always)
(with-eval-after-load 'dired
(bind-key "RET" 'dired-open-in-accordance-with-situation dired-mode-map)
(bind-key "e" 'wdired-change-to-wdired-mode dired-mode-map)
(bind-key "o" 'dired-view-file-other-window dired-mode-map)
(bind-key "[" 'dired-hide-details-mode dired-mode-map)
(bind-key "a" 'dired-list-all-mode dired-mode-map)
(bind-key "q" 'dired-dwim-quit-window dired-mode-map)
(bind-key "W" 'dired-get-fullpath-filename dired-mode-map) ;; w:file name only
(bind-key "z" 'dired-zip-files dired-mode-map) ;; Create an archive containing the marked files
(bind-key "<left>" 'dired-up-alternate-directory dired-mode-map)
(bind-key "<right>" 'dired-open-in-accordance-with-situation dired-mode-map)
(bind-key "C-x C-j" 'dired-jump))
;; direx
(setq direx:leaf-icon " " direx:open-icon "▾ " direx:closed-icon "▸ ")
(push '(direx:direx-mode :position left :width 30 :dedicated t)
popwin:special-display-config)
(bind-key [f11] 'direx:jump-to-project-directory)
(defun direx:jump-to-project-directory ()
"If in project, launch direx-project otherwise start direx."
(interactive)
(let ((result (ignore-errors
(direx-project:jump-to-project-root-other-window)
t)))
(unless result
(direx:jump-to-directory-other-window))))
;; When dired opened in two windows, move or copy in the other dired
(setq dired-dwim-target t)
;; Recursively copy directory
(setq dired-recursive-copies 'always)
;; Dired with directory first
(use-package ls-lisp)
(setq ls-lisp-use-insert-directory-program nil ls-lisp-dirs-first t)
;; Add [Dir] to the directory buffer
(defun dired-my-append-buffer-name-hint ()
"Append a auxiliary string to a name of dired buffer."
(when (eq major-mode 'dired-mode)
(let* ((dir (expand-file-name list-buffers-directory))
;; Add a drive letter for Windows
(drive (if (and (eq 'system-type 'windows-nt)
(string-match "^\\([a-zA-Z]:\\)/" dir))
(match-string 1 dir) "")))
(rename-buffer (concat (buffer-name) " [" drive "dir]") t))))
(add-hook 'dired-mode-hook 'dired-my-append-buffer-name-hint)
;; Toggle listing dot files in dired
;; https://github.com/10sr/emacs-lisp/blob/master/docs/elpa/dired-list-all-mode-20161115.118.el
(when (require 'dired-list-all-mode nil t)
(setq dired-listing-switches "-lhFG"))
;; Quit-window according to screen division
(defun dired-dwim-quit-window ()
"`quit-window 'according to screen division."
(interactive)
(quit-window (not (delq (selected-window) (get-buffer-window-list)))))
;; Get fullpath-filename with W (for file name only w)
(defun dired-get-fullpath-filename ()
"Copy file name (full path) of cursor position."
(interactive)
(kill-new (dired-get-filename))
(message (dired-get-filename)))
;; File are opened in separate buffer, directories are opened in same buffer
;; http://nishikawasasaki.hatenablog.com/entry/20120222/1329932699
(defun dired-open-in-accordance-with-situation ()
"Files are opened in separate buffers, directories are opened in the same buffer."
(interactive)
(let ((file (dired-get-filename)))
(if (file-directory-p file)
(dired-find-alternate-file)
(dired-find-file))))
;; View-file-other-window
;; http://y0m0r.hateblo.jp/entry/20120219/1329657774
(defun dired-view-file-other-window ()
"View-file other window."
(interactive)
(let ((file (dired-get-file-for-visit)))
(if (file-directory-p file)
(or (and (cdr dired-subdir-alist)
(dired-goto-subdir file))
(dired file))
(view-file-other-window file))))
;; Move to higher directory without make new buffer
(defun dired-up-alternate-directory ()
"Move to higher directory without make new buffer."
(interactive)
(let* ((dir (dired-current-directory))
(up (file-name-directory (directory-file-name dir))))
(or (dired-goto-file (directory-file-name dir))
;; Only try dired-goto-subdir if buffer has more than one dir.
(and (cdr dired-subdir-alist)
(dired-goto-subdir up))
(progn
(find-alternate-file up)
(dired-goto-file dir)))))
;; Automatic deletion for empty files (Valid in all modes)
;; https://uwabami.github.io/cc-env/Emacs.html#org57f6557
(defun my:delete-file-if-no-contents ()
"Automatic deletion for empty files."
(when (and (buffer-file-name (current-buffer))
(= (point-min) (point-max)))
(delete-file
(buffer-file-name (current-buffer)))))
(if (not (memq 'my:delete-file-if-no-contents after-save-hook))
(setq after-save-hook
(cons 'my:delete-file-if-no-contents after-save-hook)))
;; Hide .DS_Store when dotfiles listed
(when (eq system-type 'darwin)
(use-package dired-x)
(setq dired-omit-mode t)
(setq-default dired-omit-files-p t)
(setq dired-omit-files "^\\.DS_Store\\|^\\.dropbox"))
;; zip file can be expanded with Z key
(eval-after-load "dired-aux"
'(add-to-list 'dired-compress-file-suffixes
'("\\.zip\\'" ".zip" "unzip")))
;; Create an archive containing the marked files
;; https://stackoverflow.com/questions/1431351/how-do-i-uncompress-unzip-within-emacs
(defun dired-zip-files (zip-file)
"Create an archive containing the marked files."
(interactive "sEnter name of zip file: ")
;; create the zip file
(let ((zip-file (if (string-match ".zip$" zip-file) zip-file (concat zip-file ".zip"))))
(shell-command
(concat "zip "
zip-file
" "
(concat-string-list
(mapcar
'(lambda (filename)
(file-name-nondirectory filename))
(dired-get-marked-files))))))
(revert-buffer))
(defun concat-string-list (list)
"Return a string which is a concatenation of all elements of the list separated by spaces"
(mapconcat '(lambda (obj) (format "%s" obj)) list " "))
;; hydra-dired
(define-key dired-mode-map
"."
(defhydra hydra-dired (:hint nil :color pink)
"
_+_ mkdir _v_iew _m_ark _z_ip _w_ get filename _r_oot-dir _T_erminal
_C_opy view _o_ther _U_nmark all un_Z_ip _W_ get fullpath _h_ome-dir _F_inder
_D_elete open _f_ile _u_nmark _s_ort _g_ revert buffer _b_ook-dir counsel-_T_ramp
_R_ename ch_M_od _t_oggle _e_dit _[_ hide detail _d_ropbox _._togggle hydra
"
("[" dired-hide-details-mode)
("+" dired-create-directory)
("RET" dired-open-in-accordance-with-situation :exit t)
("f" dired-open-in-accordance-with-situation :exit t)
("C" dired-do-copy) ;; Copy all marked files
("D" dired-do-delete)
("M" dired-do-chmod)
("m" dired-mark)
("o" dired-view-file-other-window :exit t)
("?" dired-summary :exit t)
("R" dired-do-rename)
("a" dired-list-all-mode)
("g" revert-buffe)
("e" wdired-change-to-wdired-mode :exit t)
("s" dired-sort-toggle-or-edit)
("T" counsel-tramp :exit t)
("t" dired-toggle-marks)
("U" dired-unmark-all-marks)
("u" dired-unmark)
("v" dired-view-file :exit t)
("w" dired-copy-filename-as-kill)
("W" dired-get-fullpath-filename)
("z" dired-zip-files)
("Z" dired-do-compress)
("b" my:book-dir)
("r" my:root-dir)
("h" my:home-dir)
("d" my:dropbox)
("F" my:finder-app)
("T" my:iterm-app)
("q" nil)
("." nil :color blue)))
(defun my:root-dir ()
"Open root dir."
(interactive)
(find-file "/"))
(defun my:home-dir ()
"Open home dir."
(interactive)
(find-file "~/"))
(defun my:dropbox ()
"Open home dir."
(interactive)
(find-file "~/Dropbox"))
(defun my:book-dir ()
"Open book dir."
(interactive)
(find-file "~/Dropbox/book/"))
(defun my:finder-app ()
"Launch for finder.app."
(interactive)
(shell-command "open -a finder.app"))
(defun my:iterm-app ()
"Launch for iterm.app."
(interactive)
(shell-command "open -a iterm.app"))
;; Local Variables:
;; byte-compile-warnings: (not free-vars callargs)
;; End:
;;; 30_dired.el ends here
Hydra-markdowm
私の場合、ブログのDraftやIdeaメモ類は全てhowmで管理し、markdown記法で書いています。(詳細は後述)
emacsのmarkdown-modeはとても便利なのですがinsertコマンドの全てのキーバインドを覚えるのは至難です。yasunippetを使うという選択肢もあると思うのですが、せっかくのmarkdowm-modeなのでhydraで便利に使えるようにしてみました。
ついでに、md2html,md2pdf,md2docx,previewなども設定しています。
;;; 40_markdown.el --- 40_markdown.el
;;; Commentary:
;;; Code:
;;(setq debug-on-error t)
(defhydra hydra-markdown (:hint nil :exit t)
"
^Format^ ^Insert^ ^Head.Foot^ ^Code.Link^ ^Move^ ^Pndoc^ ^Draft
^^^^^^--------------------------------------------------------------------------------------------
_s_torong _b_lockquote H1~H6:_a_uto _c_ode block _p_romote _H_tml h_@_w_m_
italic:_/_ pre:_:_ _f_ootnote code i_n_line _d_emote _P_DF _e_asy-hugo
リスト:_._ _t_able _r_eference _l_ink _j_:move-up _D_ocx _h_atenablog
取消線:_x_ hr:_-_ _i_mage _u_ri _k_:move-down Pre_v_iew _q_iita"
("s" markdown-insert-bold)
("/" markdown-insert-italic)
("-" markdown-insert-hr)
("x" markdown-insert-strike-through)
("b" markdown-insert-blockquote)
(":" markdown-insert-pre)
("t" markdown-insert-table)
("c" markdown-insert-gfm-code-block)
("n" markdown-insert-code)
("K" markdown-insert-kbd)
("a" markdown-insert-header-dwim)
("e" easy-hugo)
("q" (browse-url "https://qiita.com/minoruGH"))
("@" my:howm-list-all)
("m" hydra-memo/body)
("h" hydra-hatena/body)
("1" markdown-insert-header-atx-1)
("2" markdown-insert-header-atx-2)
("3" markdown-insert-header-atx-3)
("4" markdown-insert-header-atx-4)
("5" markdown-insert-header-atx-5)
("6" markdown-insert-header-atx-6)
("." markdown-insert-list-item)
("i" markdown-insert-imaget)
("l" markdown-insert-link)
("u" markdown-insert-uri)
("f" markdown-insert-footnote)
("r" markdown-insert-reference-link-dwim)
("p" markdown-promote)
("d" markdown-demote)
("j" markdown-move-down)
("k" markdown-move-up)
;; Pndoc
("H" md2html :exit t)
("P" md2pdf :exit t)
("D" md2docx :exit t)
("v" markdown-preview :exit t))
;; Syntax higlight code blocks
(setq markdown-fontify-code-blocks-natively t)
(add-hook 'markdown-mode-hook
'(lambda () (outline-minor-mode t)))
(defun md2html ()
"Generate pdf from currently open markdown."
(interactive)
(let ((filename (buffer-file-name (current-buffer))))
(shell-command-to-string
;; Place of templatete : ~/.pandoc/template/md2html.html
(concat "pandoc -f markdown -t html --template=md2html "
filename
" > "
(file-name-sans-extension filename)
".html"))))
;; Use wkhtmltopdf without latex
(defun md2pdf ()
"Generate pdf from currently open markdown."
(interactive)
(let ((filename (buffer-file-name (current-buffer))))
(shell-command-to-string
(concat "pandoc "
filename
" -f markdown -t html5 -o "
(file-name-sans-extension filename)
".pdf"))
(when (eq system-type 'gnu/linux) ;; for Debian
(shell-command-to-string
(concat "evince "
(file-name-sans-extension filename)
".pdf")))
(when (eq system-type 'darwin) ;; for macOS
(shell-command-to-string
(concat "open -a preview.app "
(file-name-sans-extension filename)
".pdf")))))
(defun md2docx ()
"Generate docx from currently open markdown."
(interactive)
(let ((filename (buffer-file-name (current-buffer))))
(shell-command-to-string
(concat "pandoc "
filename
" -t docx -o "
(file-name-sans-extension filename)
;; ".docx -V mainfont=IPAPGothic -V fontsize=16pt --toc --highlight-style=zenburn"))
".docx -V mainfont=IPAPGothic -V fontsize=16pt --highlight-style=zenburn"))
(when (eq system-type 'gnu/linux)
(shell-command-to-string
(concat "xdg-open "
(file-name-sans-extension filename)
".docx")))
(when (eq system-type 'darwin)
(shell-command-to-string
(concat "open -a pages.app "
(file-name-sans-extension filename)
".docx")))))
;; markdown-preview like github ...C-c C-c p
(setq markdown-command "pandoc"
markdown-command-needs-filename t
markdown-content-type "application/xhtml+xml"
markdown-css-paths '("https://cdn.jsdelivr.net/npm/github-markdown-css/github-markdown.min.css"
"http://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/github.min.css")
markdown-xhtml-header-content "
<meta name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no'>
<style>
body {
box-sizing: border-box;
max-width: 740px;
width: 100%;
margin: 40px auto;
padding: 0 10px;
}
</style>
<script src='http://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js'></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
document.body.classList.add('markdown-body');
document.querySelectorAll('pre[lang] > code').forEach((code) => {
code.classList.add(code.parentElement.lang);
hljs.highlightBlock(code);
});
});
</script>
")
;; Local Variables:
;; byte-compile-warnings: (not free-vars callargs)
;; End:
;;; 40_markdown-mode.el ends here
Hydra-view-mode
長いコードなどを閲覧する時に便利なようにview-modeを設定しています。
一文字削除、一行削除、undoなどvim風な簡単な機能もつけました。magitやgit-gutterも使えます。大げさな割にはそれほど使わないのですが、まあ自己満足の世界です(^o^)。
;;; 40_view-mode.el --- 40_view-mode.el
;;; Commentary:
;;; Code:
;;(setq debug-on-error t)
;; Change modeline color in view-mode
(use-package viewer)
(setq viewer-modeline-color-view "#852941")
(viewer-change-modeline-color-setup)
;; Setting to utilize view-mode
(key-chord-define-global "::" 'view-mode)
(add-hook 'view-mode-hook
(lambda ()
(define-key view-mode-map "i" 'View-exit)
(define-key view-mode-map ":" 'View-exit)
(define-key view-mode-map "g" 'beginning-of-buffer)
(define-key view-mode-map "G" 'end-of-buffer)
(define-key view-mode-map "e" 'end-of-line)
(define-key view-mode-map "a" 'beginning-of-line)
(define-key view-mode-map "b" 'scroll-down-command)
(define-key view-mode-map "D" 'my/view-kill-whole-line)
(define-key view-mode-map "u" 'my/view-undo)
(define-key view-mode-map "X" 'my/view-del-char)
(define-key view-mode-map "w" 'my/view-forward-word+1)
(define-key view-mode-map "W" 'backward-word)
(define-key view-mode-map "s" 'swiper-for-region-or-swiper)
(define-key view-mode-map "t" 'git-timemachine)
(define-key view-mode-map "v" 'vc-diff)
(define-key view-mode-map "[" 'forward-list)
(define-key view-mode-map "]" 'backward-list)
(define-key view-mode-map "l" 'goto-line)
(define-key view-mode-map ";" 'recenter-top-bottom)
(define-key view-mode-map "m" 'magit-status)
(define-key view-mode-map "B" 'magit-blame)
(define-key view-mode-map "j" 'git-gutter:next-hunk)
(define-key view-mode-map "k" 'git-gutter:previous-hunk)
(define-key view-mode-map "r" 'git-gutter:revert-hunk)
(define-key view-mode-map "S" 'git-gutter:stage-hunk)
(define-key view-mode-map "p" 'git-gutter:popup-hunk)
(define-key view-mode-map "," 'hydra-window/body)
(define-key view-mode-map "_" 'delete-other-windows)
(define-key view-mode-map "." 'hydra-view-mode/body)))
;; Function to edit in view-mode
(defun my/view-forward-word+1 ()
"Forward word+1 in view mode."
(interactive)
(forward-word)
(forward-char))
(defun my/view-kill-whole-line ()
"Kill whole line in view mode."
(interactive)
(view-mode 0)
(kill-whole-line)
(save-buffer)
(view-mode 1)
(message "kill-whole-line and save!"))
(defun my/view-del-char ()
"Delete character in view mode."
(interactive)
(view-mode 0)
(delete-char 1)
(save-buffer)
(view-mode 1)
(message "delete-char"))
(defun my/view-undo ()
"Undo in view mode."
(interactive)
(view-mode 0)
(undo)
(save-buffer)
(view-mode 1)
(message "undo and save!"))
;; hydra-view-mode
(defhydra hydra-view-mode (:hint nil :color pink)
"
_SPC_: next page _a_: top of line _u_: view undo _m_: magit-status _j_: gg:next-hunk _s_: swiper
_b_: prev page _e_: end of line _w_: forward word _B_: magit-blame _k_: gg:prev-hunk _d_: dired-jump
_g_: page top _l_: goto line _W_: backward word _t_: timemachine _p_: gg:popup-hunk _i_: view exit
_G_: page end _D_: delete line _[_: forward pair _v_: vc-diff _S_: gg:stage-hunk _q_: view quit
_;_: top-bottom _X_: delete char _]_: backward pair _h_: github _r_: gg:revert-hun _._: close
"
;; Move page
("SPC" scroll-up-command)
("b" scroll-down-command)
("g" beginning-of-buffer)
("G" end-of-buffer)
;; Move line
("a" beginning-of-line)
("e" end-of-line)
("w" my/view-forward-word+1)
("W" backward-word)
("D" my/view-kill-whole-line)
("X" my/view-del-char)
("u" my/view-undo)
;; Misc
("i" View-exit :exit t)
("q" View-quit :exit t)
(":" View-exit :exit t)
("[" forward-list)
("]" backward-lis)
("l" goto-line)
;; git
("v" vc-diff)
("m" magit-status :exit t)
("B" magit-blame :exit t)
("t" git-timemachine :exit t)
("h" my/github)
;; gitgutter
("j" git-gutter:next-hunk)
("k" git-gutter:previous-hunk)
("p" git-gutter:popup-hunk)
("S" git-gutter:stage-hunk)
("r" git-gutter:revert-hunk)
(";" recenter-top-bottom)
;; Others
("d" dired-jump :exit t)
("_" delete-other-windows :exit t)
("s" swiper-for-region-or-swiper)
("," hydra-window/body :exit t)
("." nil :color blue))
;; Local Variables:
;; byte-compile-warnings: (not free-vars callargs)
;; End:
;;; 40_view-mode.el ends here
Hydra-browse
何でもかんでもemacsを作業デスクとしてして生活しているので、色んな場所へジプシーするためのお気に入りランチャーです。macアプリもいれました。
;;; 50_hydra-browse.el --- 50_hydra-browse.el
;;; Commentary:
;;; Code:
;;(setq debug-on-error t)
(bind-key
[f10]
(defhydra hydra-browse (:hint nil :exit t)
"
^Shop^ ^SNS^ ^Repos^ ^GH^ ^Favorite^ ^Others^ ^Applications
^^^^^^---------------------------------------------------------------------------------------------------
_a_: Amazon _t_: Twitter _g_: github _h_: HOME _j_: Jorudan _D_: Dropbox _c_: Browse-url
_r_: Rakuten _u_: Youtube _0_: gist _d_: d.kukai _n_: News _x_: Xserver _l_: ForkLift
_y_: Yodobashi _f_: Flickr _1_: masasam _m_: m.kukai _w_: Weather _q_: Qiita _@_: Airmail
_k_: Kakaku _e_: Evernote _2_: hydraWiki _b_: BBS _B_: SanyoBas _p_: Photo(G) _i_: iTerm
"
("a" (browse-url "https://www.amazon.co.jp/"))
("r" (browse-url "https://www.rakuten.co.jp/"))
("y" (browse-url "https://www.yodobashi.com/"))
("k" (browse-url "http://kakaku.com/"))
("t" (browse-url "https://twitter.com"))
("u" (browse-url "https://www.youtube.com/channel/UCnwoipb9aTyORVKHeTw159A/videos"))
("f" (browse-url "https://www.flickr.com/photos/minorugh/"))
("e" (browse-url "https://www.evernote.com/client/web#?an=true&n=02ab918a-18a7-472b-a166-835a922d3fad&s=s278&"))
("g" (browse-url "https://github.com/minorugh/emacs.d"))
("0" (browse-url "https://gist.github.com/minorugh"))
("_" (browse-url "https://github.com/minorugh/emacs.d/"))
("1" (browse-url "https://github.com/masasam/dotfiles/tree/master/.emacs.d"))
("2" (browse-url "https://github.com/abo-abo/hydra/wiki"))
("h" (browse-url "http://gospel-haiku.com/"))
("d" (browse-url "http://gospel-haiku.com/d_kukai/"))
("m" (browse-url "http://gospel-haiku.com/m_kukai/"))
("b" (browse-url "http://gospel-haiku.com/danwa/"))
("j" (browse-url "https://www.jorudan.co.jp/"))
("n" (browse-url "https://news.yahoo.co.jp/"))
("w" (browse-url "https://tenki.jp/week/6/31/"))
("B" (browse-url "http://www.sanyo-bus.co.jp/pdf/180913.pdf"))
("x" (browse-url "https://www.xserver.ne.jp/login_server.php"))
("D" (browse-url "https://www.dropbox.com/home/documents"))
("q" (browse-url "https://qiita.com/minoruGH"))
("v" (browse-url "https://drive.google.com/drive/u/0/my-drive"))
("p" (browse-url "https://photos.google.com/?pageId=none"))
("/" kill-other-buffers)
("," hydra-window/body)
("." hydra-work1/body)
("c" browse-url-at-point)
("s" my:skitch-app)
("l" my:forklift-app)
("@" my:amail-app)
("i" my:iterm-app)
("<f10>" nil)))
;; Launch for Mac applications
(defun my:calendar-app ()
"Launch for calendar.app."
(interactive)
(shell-command "open -a calendar.app"))
(defun my:forklift-app ()
"Launch for forklift.app."
(interactive)
(shell-command "open -a forklift.app"))
(defun my:amail-app ()
"Launch for airmail3.app."
(interactive)
(shell-command "open -a 'airmail 3.app'"))
(defun my:iterm-app ()
"Launch for iterm.app."
(interactive)
(shell-command "open -a iterm.app"))
(defun my:skitch-app ()
"Launch for skitch.app."
(interactive)
(shell-command "open -a skitch.app"))
;; Local Variables:
;; byte-compile-warnings: (not free-vars callargs)
;; End:
;;; 50_hydra-browse.el ends here
Hydra-compile
同じことは2度しない。必ずしなければ習い作業 → 自動化できないか考える。
これは私が原点としている心がけですが、尊敬する故・石井 勝氏による下記記事の受け売りです。
emacsには、compile
というコマンドがあり、デフォルトで make -k
を実行してくれます。
それ以外のmakeコマンドを実行させたいときは、deleteで “-k” の部分を消して書き換えるのですが、そうすると次回 compile
コマンドを実行したときに make -k
にならないで書き換えたものに置き換えられてしまいますう。それらを解決するためにhydraで工夫してみました。
make -k
以外のときは、shell-command
を使います。
;;; 50_hydra-compile.el --- 50_hydra-compile.el
;;; Commentary:
;;; Code:
;;(setq debug-on-error t)
(bind-key
[f2]
(defhydra hydra-make (:color red :hint nil)
"
Command: _RET_:compile _u_pftp _m_ove _b_klog _g_it _c_lean _r_estore:compile-command"
("RET" compile)
("u" my:make-upftp :exit t)
("m" my:make-move :exit t)
("g" my:make-git :exit t)
("b" my:make-bklog :exit t)
("c" my:make-clean)
("r" my:restore-command)))
(defun my:make-upftp ()
"Make command for upftp."
(interactive)
(shell-command "make up"))
(defun my:make-move ()
"Make command for move."
(interactive)
(shell-command "make mv"))
(defun my:make-bklog ()
"Make command for bklog."
(interactive)
(shell-command "make bk"))
(defun my:make-git ()
"Make command for git."
(interactive)
(shell-command "make git"))
(defun my:make-clean ()
"Make command for clean."
(interactive)
(shell-command "make clean"))
(defun my:restore-command ()
"Restore for compile command."
(interactive)
(setq compile-command "make -k")
(message "Restored!"))
;; Local Variables:
;; byte-compile-warnings: (not free-vars callargs)
;; End:
;;; 50_hydra-compile ends here
Hydra-window
ネット上でも最近良く見かけるemacsのwindow制御です。
正直、“C-x ..” を叩く癖が身についているのでそれほど便利な気はしませんが、swap,toggle-divosionのほか、frameにも対応させています。
hydraとは別に window移動:other-window-or-split
を “C-q” にも割り当てています。私の場合、二分割を超えて使うことは先ずないので、
慣れ親しんだこちらのほうが使いやすいです。
;;; 50_hydra-window.el --- 50_hydra-window.el
;;; Commentary:
;;; Code:
;;(setq debug-on-error t)
(bind-key
[f7]
(defhydra hydra-window (:color red :hint nil)
"
Window: _v_sprit _h_sprit _o_ther _s_wap e_x_change del_0_:_1_ | Frame: _n_ew _m_ove _d_el"
("v" split-window-right)
("h" split-window-below)
("o" other-window-or-split)
("s" window-swap-states)
("x" window-toggle-division)
("0" delete-window :exit t)
("1" delete-other-windows :exit t)
;; Common setting with hydra-work
("_" delete-other-windows :exit t)
("n" new-frame)
("m" other-frame)
("d" delete-frame :exit t)))
(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))
(bind-key "C-q" 'other-window-or-split)
(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)))
;; Local Variables:
;; byte-compile-warnings: (not free-vars callargs)
;; End:
;;; 50_hydra-window.el ends here
Hydra-howm
私はemacsでタスク管理はしないのでorg-modeには余り興味がなくシンプルなhowmを愛用しています。
そのhowmも本来の使い方ではなく “メモデーターの保存と管理” 目的で使っています。メモの種類は以下のとおりです。
- ブログ記事などの下書き: howm-create で書く
- ちょこっとしたアイデアメモ: howm-remember で書く
- 俳句創作手帳: elispコマンドでtemplateを挿入
- open-junk-file: いわゆる自作のちょこっとしたジュンクコード
上記それぞれ保存するデレクトリは分けて別々に一覧表示させるのですが、全てをhowmディレクトリ下に配置することで全ファイルを串刺し検索できるようにもしています。長くなるので詳細は別記事にしたいと思います。
;;; 60_howm.el --- 60_howm.el
;;; Commentary:
;;; Code:
;;(setq debug-on-error t)
;; Set the title-hearder chara first and then reqire howm.
(setq howm-view-title-header "#")
(use-package howm)
;; List buffer and content buffer side by side
(setq howm-view-split-horizontally t)
;; Clear list buffer when opening file with RET
(setq howm-view-summary-persistent nil)
;; List in descending order
(setq howm-list-normalizer 'howm-view-sort-by-reverse-date)
;; hydra
(defhydra hydra-howm (:hint nil :exit t)
"
HOWM: _c_reate _m_emo _f_ile // LIST: mem_o_ _h_aiku _j_unk all_@_"
("c" my:howm-create)
("m" my:howm-memo-create)
("f" open-junk-file)
("o" my:howm-memo-list-all)
("h" my:howm-haiku-list-all)
("j" my:howm-junk-list-all)
("@" my:howm-list-all))
;; open-junk-file
(setq open-junk-file-format "~/Dropbox/howm/junk/%Y/junk.%Y%m%d.")
;; Set howm directory and file name format
(defun my:howm-create ()
"My howm memo create."
(interactive)
(setq howm-directory "~/Dropbox/howm")
(setq howm-file-name-format "%Y/%m/%Y%m%d%H%M.md")
(howm-create))
(defun my:howm-memo-create ()
"My howm memo create."
(interactive)
(setq howm-directory "~/Dropbox/howm/memo")
(setq howm-file-name-format "%Y/%m/memo-%Y%m%d.md")
(howm-remember))
;; Set howm directory for list display
(defun my:howm-memo-list-all ()
"My howm memo list all."
(interactive)
(setq howm-directory "~/Dropbox/howm/memo")
(howm-list-all))
(defun my:howm-list-all ()
"My howm list all."
(interactive)
(setq howm-directory "~/Dropbox/howm")
(howm-list-all))
(defun my:howm-haiku-list-all ()
"My howm list all."
(interactive)
(setq howm-directory "~/Dropbox/howm/haiku")
(howm-list-all))
(defun my:howm-junk-list-all ()
"My howm list all."
(interactive)
(setq howm-directory "~/Dropbox/howm/junk")
(howm-list-all))
;; Local Variables:
;; byte-compile-warnings: (not free-vars callargs)
;; End:
;;; 60_howm.el ends here
Hydra-search-web
必須のgoogle-translateは別設定です。
googole-this とかを使うTipsも多いですが、私は昔から、search-web というパッケージを愛用しています。簡単な設定で自由にカスタマイズすることができて様々な検索サイトを利用することが出来るからです。
郵便番号から住所を検索したりgoogle−mapやgoogle-earthを検索すると圧巻です。
;;; 50_hydra-search-web.el --- 50_hydra-search-web.el
;;; Commentary:
;;; Code:
;;(setq debug-on-error t)
(use-package search-web)
(add-to-list 'search-web-engines '("weblio" "http://weblio.jp/content/%s" nil))
(add-to-list 'search-web-engines '("kobun" "http://kobun.weblio.jp/content/%s" nil))
(add-to-list 'search-web-engines '("ruigo" "http://thesaurus.weblio.jp/content/%s" nil))
(add-to-list 'search-web-engines '("github" "https://github.com/search?utf8=✓&q=%s&ref=simplesearch" nil))
(add-to-list 'search-web-engines '("qitta" "https://qiita.com/search?q=%s" nil))
(add-to-list 'search-web-engines '("post" "https://postcode.goo.ne.jp/search/q/%s/" nil))
(add-to-list 'search-web-engines '("earth" "https://earth.google.com/web/search/%s/" nil))
(bind-key
"s-s"
(defhydra hydra-search-web (:color red :hint nil)
"
Search: _a_mazon _g_oogle _t_ranslate _e_ijiro _m_aps git_h_ub _q_itta _w_eblio _p_〒 _k_古語 _r_類語 _._close"
("a" (search-web-dwim "amazon jp"))
("e" (search-web-dwim "eijiro"))
("g" (search-web-dwim "google"))
("m" (search-web-dwim "google maps"))
("h" (search-web-dwim "github"))
("q" (search-web-dwim "qitta"))
("w" (search-web-dwim "weblio"))
("p" (search-web-dwim "post"))
("k" (search-web-dwim "kobun"))
("r" (search-web-dwim "ruigo"))
("t" google-translate-auto)
("q" nil)
("." nil :color blue)))
;; Local Variables:
;; byte-compile-warnings: (not free-vars callargs)
;; End:
;;; 50_hydra-search-web.el ends here
まとめ
とりいそぎざっくりと紹介しました。自作のコードはほとんどなく大半はパッチワークです。
Emacsの設定ファイルはGitHubに公開していますので興味ある方は覗いてみてください。