Skip to content

Instantly share code, notes, and snippets.

@tam17aki
Last active January 14, 2024 14:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tam17aki/650d16384f3b33089228fcebfa678b6e to your computer and use it in GitHub Desktop.
Save tam17aki/650d16384f3b33089228fcebfa678b6e to your computer and use it in GitHub Desktop.
;; C-zを無効化
(global-unset-key "\C-z")
;; ロードパスを追加
(add-to-list 'load-path "~/.emacs.d/lisp/")
;; theme
(if (display-graphic-p)
(load-theme 'solarized-light t))
;; (load-theme 'solarized-light t)
;; 言語設定 & mozc
(set-language-environment 'utf-8)
(setq default-input-method "japanese-mozc")
(prefer-coding-system 'utf-8)
(with-eval-after-load 'mozc
(require 'mozc-popup)
(setq mozc-candidate-style 'popup)
(require 'mozc-temp)
(setq mozc-temp-remove-pre-space nil) ;; 変換時のpreスペース削除を抑制する
(global-set-key (kbd "M-j") #'mozc-temp-convert))
;; tab-bar
(desktop-save-mode 1) ;; tabの構成を含めて復元できる(実質的な永続化の実現)
(with-eval-after-load 'tab-bar
(setq tab-bar-tab-hints t) ;; タブに番号表示
(setq tab-bar-new-button-show nil) ;; 新規タブボタンは非表示
(setq tab-bar-close-button-show nil) ;; タブ削除ボタンは非表示
(setq tab-bar-format '(tab-bar-format-tabs tab-bar-separator)) ;; ヒストリのボタンは不要
(tab-bar-history-mode 1) ;; 各タブについて,ウィンドウ構成のヒストリを記憶する
;; タブ名に保持しているウィンドウの数を付記する
(setq tab-bar-tab-name-function 'tab-bar-tab-name-current-with-count)
;; タブ番号に基づいてワンストロークで移動する
(defvar tab-bar-switch-prefix "C-M-%d") ;; C-M-1はタブ番号1への移動, C-M-2はタブ番号2への移動
(defvar tab-bar-top-tab "1")
(defvar tab-bar-bottom-tab "9")
(defun tab-bar-set-keybind ()
(mapc (lambda (i)
(global-set-key (kbd (format tab-bar-switch-prefix i))
`(lambda ()
(interactive)
(tab-bar-select-tab ,(int-to-string i)))))
(number-sequence (string-to-number tab-bar-top-tab)
(string-to-number tab-bar-bottom-tab))))
(tab-bar-set-keybind))
;; eww
(setq eww-search-prefix "https://www.google.co.jp/search?q=")
(setq shr-use-fonts nil)
(add-hook 'eww-mode-hook
#'(lambda ()
(defun eww-mode-hook--rename-buffer ()
"Rename eww browser's buffer so sites open in new page."
(rename-buffer "eww" t))
(add-hook 'eww-mode-hook 'eww-mode-hook--rename-buffer)
(defun eww-disable-images ()
"eww で画像表示させない"
(interactive)
(setq-local shr-put-image-function 'shr-put-image-alt)
(eww-reload))
(defun eww-enable-images ()
"eww で画像表示させる"
(interactive)
(setq-local shr-put-image-function 'shr-put-image)
(eww-reload))
(defun shr-put-image-alt (spec alt &optional flags)
(insert alt))
;; はじめから非表示
(defun eww-mode-hook--disable-image ()
(setq-local shr-put-image-function 'shr-put-image-alt))
(eww-mode-hook--disable-image)
(display-line-numbers-mode -1)))
(with-eval-after-load "eww"
(ace-link-setup-default)
(define-key eww-mode-map (kbd "o") #'ace-link-eww)
(define-key eww-mode-map "r" 'eww-reload)
(define-key eww-mode-map "c 0" 'eww-copy-page-url)
(define-key eww-mode-map "p" 'scroll-down)
(define-key eww-mode-map "n" 'scroll-up)
(defvar eww-disable-colorize t)
(defun shr-colorize-region--disable (orig start end fg &optional bg &rest _)
(unless eww-disable-colorize
(funcall orig start end fg)))
(advice-add 'shr-colorize-region :around #'shr-colorize-region--disable)
(advice-add 'eww-colorize-region :around #'shr-colorize-region--disable)
(defun eww-disable-color ()
"eww で文字色を反映させない"
(interactive)
(setq-local eww-disable-colorize t)
(eww-reload))
(defun eww-enable-color ()
"eww で文字色を反映させる"
(interactive)
(setq-local eww-disable-colorize nil)
(eww-reload)))
;; Emacs29
(global-set-key (kbd "C-x j") #'duplicate-dwim)
(defun open-line-upper (&optional arg)
"カーソルから1つ上の行にインデント付きで空行挿入"
(interactive "p")
(if (eq arg 4)
(open-line 1)
(let ((value 0))
(dotimes (i arg value)
(cond ((bolp)
(progn
(newline-and-indent)
(forward-line -1)
(indent-for-tab-command)
(beginning-of-line)))
(t
(save-excursion
(beginning-of-line)
(open-line 1)
(indent-according-to-mode))))))))
(defun open-line-lower (&optional arg)
"カーソルから1つ下の行にインデント付きで空行挿入"
(interactive "p")
(if (eq arg 4)
(open-line 1)
(let ((value 0))
(dotimes (i arg value)
(save-excursion
(end-of-line)
(newline nil t)
(indent-according-to-mode)
(indent-for-tab-command))))))
;; C-M-oはインデントを保ったままカーソル下のバッファ全体を1行下にずらす
(global-set-key (kbd "M-o") 'open-line-lower)
(global-set-key (kbd "M-O") 'open-line-upper)
(defun kill-whole-line2 ()
(interactive)
(kill-whole-line)
(back-to-indentation))
(global-set-key (kbd "C-S-k") 'kill-whole-line2)
;; 起動時の画面をオフ
(setq inhibit-startup-message t)
;; 警告音を完全に消す
(setq ring-bell-function 'ignore)
;;リージョンに色をつける
(setq transient-mark-mode t)
;; 折り返し表示
(setq truncate-lines nil)
;; 起動時のフレームサイズを設定する
(setq initial-frame-alist
(append (list
'(width . 180)
'(height . 55)
'(top . 0)
'(left . 100))
initial-frame-alist))
(setq default-frame-alist initial-frame-alist)
;; ツールバーを非表示
(tool-bar-mode -1)
;; カーソルを点滅させない
(blink-cursor-mode -1)
;; 余計なファイルを生成させない
(setq make-backup-files nil)
(setq auto-save-default nil)
(setq auto-save-list-file-prefix nil)
;; C-x C-c で閉じる時に、ワンクッション置く
(setq confirm-kill-emacs 'y-or-n-p)
;; バックアップファイルを作らない
(setq backup-inhibited t)
;; t: 行全体を削除
(setq kill-whole-line t)
;; set tab width as 4
(setq-default tab-width 4)
;; tab width = 4
(setq tab-stop-list (number-sequence 4 60 4))
;; インデントはスペースで
(setq-default indent-tabs-mode nil)
;; auto-revert (emacs以外からファイル編集されたときに再読込)
(global-auto-revert-mode t)
;; ウィンドウのタイトルに
;; バージョン名,ファイルのフルパス,日付・時刻を表示する
;; https://qiita.com/fujimotok/items/28b03a05224cedd0cc5a
(setq display-time-interval 30)
(setq display-time-string-forms
'((format "[ %s/%s/%s(%s) %s:%s ]"
year month day dayname 24-hours minutes)))
;; year (A.D.)
;; month (1 -> 12)
;; day (1 -> 31)
;; dayname -- Sun, Mon, Tue, Wed, Thu, Fri, Sat
;; 24-hours (0 -> 23)
;; minutes (0 -> 59)
;; seconds (0 -> 59)
;; display date on the left side of time
(setq display-time-24hr-format t)
(setq display-time-day-and-date t)
(defvar title-time-mode t
"This is set to t iff we are displaying the current time in the title bar.")
(defun title-time-set ()
"Set `frame-title-format' to the local system name followed by date,
time, and load information (as per `display-time-string-forms') and perhaps
followed by an appointment notification."
(setq frame-title-format
(concat (format "Emacs%s: %%f" emacs-version)
" - " display-time-string)))
(defun title-time-update ()
"Update the time display in the title-bar.
Skips inferior frames, that is, those without a minibuffer (eg. speedbar). "
(interactive)
;; remove time display from the mode line
(delq 'display-time-string global-mode-string)
(delq 'appt-mode-string global-mode-string)
(let ((start-frame (selected-frame)))
(save-excursion
(save-window-excursion
(let ((my-frame-list (frame-list))
(my-frame nil))
(while (setq my-frame (car my-frame-list))
(when (frame-parameter my-frame 'minibuffer)
(frame-parameter nil 'frame-title-format)
(select-frame my-frame)
(title-time-set))
(setq my-frame-list (cdr my-frame-list))))))
(select-frame start-frame)))
(add-hook 'display-time-hook #'title-time-update)
;; 時間表示
(display-time-mode 1)
;; バッファ名の一意化
(setq uniquify-buffer-name-style 'post-forward-angle-brackets)
(setq uniquify-ignore-buffers-re "*[^*]+*")
;; リージョンを選択中に入力したテキストで上書き
(delete-selection-mode 1)
(defun my/exchange-point-and-mark ()
"`exchange-point-and-mark' without mark activatation."
(interactive)
(exchange-point-and-mark)
(deactivate-mark))
(global-set-key (kbd "C-x C-x") 'exchange-point-and-mark)
(global-set-key (kbd "C-x C-.") 'my/exchange-point-and-mark)
;; ウィンドウ構成を記憶し,undo/redoできる
;; winner-undo, winner-redo
;; (winner-mode)
;; 気の利いた補完
;; dabbrev-expandとdabbrev-completionを交換
;; (global-set-key (kbd "C-M-/") #'dabbrev-expand)
;; (global-set-key (kbd "M-/") #'dabbrev-completion)
;; capeは completion-at-point-functions に追加する便利関数を提供
(add-to-list 'completion-at-point-functions #'cape-dabbrev)
(global-set-key (kbd "C-M-/") #'cape-dabbrev)
;; (global-set-key (kbd "C-t") #'cape-dabbrev)
;; C-M-i は completion-at-point; corfuが走る
;; C-M-/ は dabbrev-completion;
;; Like M-x dabbrev-expand but finds all expansions in the current buffer
;; and presents suggestions for completion.
;; → dabbrev-expand より広く候補を探しつつ、補完候補を示してくれる
;; dabbrev-capf は 現在バッファからのdabbrev?
(add-to-list 'completion-at-point-functions #'dabbrev-capf)
(with-eval-after-load 'dabbrev
(add-to-list 'dabbrev-ignored-buffer-regexps "\\` ")
(add-to-list 'dabbrev-ignored-buffer-modes 'doc-view-mode)
(add-to-list 'dabbrev-ignored-buffer-modes 'pdf-view-mode))
(setq dabbrev-case-fold-search nil) ;; nil 検索時に大文字と小文字を区別する
(setq dabbrev-case-replace nil) ;; nil 展開時に大文字と小文字を区別する
;; (global-set-key (kbd "C-t") 'hippie-expand)
(setq hippie-expand-try-functions-list
'(
try-expand-dabbrev
try-expand-dabbrev-all-buffers
;; try-expand-dabbrev-from-kill
try-complete-lisp-symbol-partially
try-complete-lisp-symbol
try-complete-file-name-partially
try-complete-file-name
try-expand-all-abbrevs
;; try-expand-list
;; try-expand-line
))
;; mode-lineにウィンドウ番号を表示,ALT+数字キーで移動
(window-numbering-mode +1)
;; リージョンを選択中に入力したテキストで上書き
(delete-selection-mode 1)
;;; ナローイングを有効化
(put 'narrow-to-region 'disabled nil)
(put 'narrow-to-page 'disabled nil)
(put 'narrow-to-defun 'disabled nil)
(global-set-key (kbd "<left>") #'windmove-left)
(global-set-key (kbd "<down>") #'windmove-down)
(global-set-key (kbd "<up>") #'windmove-up)
(global-set-key (kbd "<right>") #'windmove-right)
(defun split-window-above (&optional size)
"画面分割したとき下のウィンドウがアクティヴになる."
(interactive)
(split-window nil size 'above))
(global-set-key "\C-x2" #'split-window-above)
(defun split-window-left (&optional size)
"画面分割したとき右のウィンドウがアクティヴになる."
(interactive)
(split-window nil size 'left))
(global-set-key "\C-x3" #'split-window-left)
;; インデントの改善
(defun all-indent ()
(interactive)
(save-excursion
(indent-region (point-min) (point-max))))
(defun electric-indent ()
(interactive)
(if (use-region-p)
(indent-region (region-beginning) (region-end))
(all-indent)))
;; 行番号の表示
(setq-default indicate-empty-lines t)
(setq-default indicate-buffer-boundaries 'left)
(column-number-mode)
;; 長いファイルを開く場合でも行番号を常に表示
(setq line-number-display-limit-width 100000)
(add-hook 'prog-mode-hook #'display-line-numbers-mode)
;; モードラインに現在行数と総行数を同時に表示
(defvar my-mode-line-format nil)
(setq my-mode-line-format " (%%l/%d,%%c)")
(if size-indication-mode
(setq my-mode-line-format (concat my-mode-line-format " of %%I")))
(setq mode-line-position
'(:eval (format my-mode-line-format
(count-lines (point-min) (point-max)))))
;; 今バッファに表示している範囲を(矢印を用いて)フリンジに表示する
(setq-default indicate-buffer-boundaries 'left)
;; C-u C-SPC C-SPC C-SPC... のように C-SPC を連続で入力するだけで,
;; 連続でマークを辿れるように
(setq set-mark-command-repeat-pop t)
;; 現在行のハイライト
;; カラムのハイライトはvline-mode
(global-hl-line-mode 1)
(keyboard-translate ?\C-h ?\C-?)
(global-set-key "\C-h" nil)
;; OS側の別アプリ経由でクリップボードにコピーした内容をEmacsに貼り付ける
(global-set-key (kbd "C-M-y") 'clipboard-yank)
;; バッファリストの表示
;; c キーでconfigを次々に変える
(global-set-key (kbd "C-x C-b") 'bs-show)
(setq bs-default-configuration "files-and-dirs")
(with-eval-after-load "bs"
(defun my-visits-non-file-or-dir (buffer)
(and (not (buffer-file-name buffer))
(not (eq (buffer-local-value 'major-mode buffer) 'dired-mode))))
(add-to-list 'bs-configurations
'("files-and-dirs" nil nil nil my-visits-non-file-or-dir
bs-sort-buffer-interns-are-last)))
(defun thingopt-init ()
(interactive)
(require 'thingopt)
(define-thing-commands)
(global-set-key (kbd "C-,") #'mark-word*)
(global-set-key (kbd "C-.") #'mark-symbol)
(global-set-key (kbd "C-M-,") #'mark-string)
(global-set-key (kbd "C-M-.") #'mark-up-list))
(add-hook 'python-mode-hook
#'(lambda ()
(thingopt-init)))
(add-hook 'emacs-lisp-mode-hook
#'(lambda ()
(thingopt-init)))
;; スクロールは1行ごとに
(setq mouse-wheel-scroll-amount '(1 ((shift) . 5)))
;; スクロールの加速をやめる
(setq mouse-wheel-progressive-speed nil)
;; optionキーをsuperに、commandキーをmetaに
(setq mac-option-modifier 'super
mac-command-modifier 'meta
mac-right-option-modifier 'none)
;; newlineを賢くする
(add-hook 'python-mode-hook
#'(lambda ()
(smart-newline-mode t)))
(add-hook 'emacs-lisp-mode-hook
#'(lambda ()
(smart-newline-mode t)))
;; undo-tree
(add-hook 'python-mode-hook
#'(lambda ()
(undo-tree-mode t)))
(with-eval-after-load 'undo-tree
(setq undo-tree-mode-lighter " UT"))
;; dired
;; C コピー(cp)
;; R リネーム/移動 (mv)
;; D 削除(rm)
;; M 権限操作(chmod)
;; G グループ変更(chgrp)
;; O 所有権変更(chown)
;; Z 圧縮/展開(compress/uncompress/gunzip/bunzip/unzip)
;; B (*.elファイルの)バイトコンパイル
;; ! 任意のコマンドの実行。デフォルトで空気読んだコマンドになってる。
;; dired-filter
;; /d ディレクトリのみ
;; /n ファイルのみ
;; /. 拡張子指定
;; /! 直前の条件の反転
;; /p 直前の条件を削除
;; // 全ての条件を削除
(add-hook 'dired-mode-hook #'dired-filter-mode)
(add-hook 'dired-mode-hook #'all-the-icons-dired-mode)
(with-eval-after-load "dired"
(define-key dired-mode-map (kbd "r") 'wdired-change-to-wdired-mode)
(define-key dired-mode-map (kbd "u") 'dired-up-directory)
;; dired上のウィンドウ切り替え(左右)
(define-key dired-mode-map
(kbd "C-M-p") #'(lambda () (interactive) (other-window -1)))
(define-key dired-mode-map
(kbd "C-M-n") #'(lambda () (interactive) (other-window 1)))
(define-key dired-mode-map (kbd "SPC") #'my-dired-quicklook)
;; ファイルを開いているときに、カレントディレクトリをdiredで開く
(defun dired-find-file-current-dir ()
"Find-file current directory"
(interactive)
(find-file default-directory))
;; ファイルサイズを読みやすくする
(setq dired-use-ls-dired nil)
(setq dired-listing-switches "-lha")
;; Dired を 2つのウィンドウで開いているときに other-window へ copy する
(defun dired-do-copy-dwim ()
(interactive)
(let ((dired-dwim-target t))
(dired-do-copy)))
;; Dired を 2つのウィンドウで開いているときに other-window へ move する
(defun dired-do-rename-dwim ()
(interactive)
(let ((dired-dwim-target t))
(dired-do-rename)))
;; Dired を 2つのウィンドウで開いているときに other-window へ symlink する
(defun dired-do-symlink-dwim ()
(interactive)
(let ((dired-dwim-target t))
(dired-do-symlink)))
;; dired-open-file でディレクトリ移動の際は、バッファをkill する関数
(defun kill-current-buffer-and/or-dired-open-file ()
"In Dired, dired-open-file for a file. For a directory, dired-find-file and
kill previously selected buffer."
(interactive)
(if (file-directory-p (dired-get-file-for-visit))
(dired-find-alternate-file)
(dired-open-file)))
;; dired-up-directory で元のバッファをkill する関数
(defun kill-current-buffer-and-dired-up-directory (&optional other-window)
"In Dired, dired-up-directory and kill previously selected buffer."
(interactive "P")
(let ((b (current-buffer)))
(dired-up-directory other-window)
(kill-buffer b)))
;; dired-open-file でディレクトリ移動のとき、別ウインドウに新たなバッファを作成し、
;; もとのバッファを選択したままにする関数
(defun dired-open-file-other-window ()
"In Dired, open file on other-window and select previously selected buffer."
(interactive)
(let ((cur-buf (current-buffer)) (tgt-buf (dired-open-file)))
(switch-to-buffer cur-buf)
(when tgt-buf
(with-selected-window (next-window)
(switch-to-buffer tgt-buf)))))
;; dired-up-directory で行き先のディレクトリのバッファを別ウインドウで開く
(defun dired-up-directory-other-window ()
"In Dired, dired-up-directory on other-window"
(interactive)
(dired-up-directory t))
(defvar my-dired-spawn nil)
(make-variable-buffer-local 'my-dired-spawn)
;; http://stackoverflow.com/a/20023781/2112489
(defun my-dired-kill-last-process-named (name)
"Function initially written by @wvxvw, and revised by @lawlist."
(let (p)
(cl-loop with name-re =
(format "^%s\\(?:<\\([[:digit:]]+\\)>\\)?" (regexp-quote name))
for process in (process-list)
for pname = (process-name process)
if (string-match name-re pname)
collect (cons (string-to-number (or (match-string 1 pname) "0")) process)
into processes
finally
(let ((process (cdar (cl-sort processes '> :key 'car))))
(when (and process (get-process process))
(delete-process process)
(setq p process))))
p))
(defun my-dired-qlmanage ()
(interactive)
(unless (my-dired-kill-last-process-named "qlmanage")
(let* ((current-node (dired-get-file-for-visit)))
(set-process-sentinel
(start-process "qlmanage" nil "/usr/bin/qlmanage" "-p" current-node)
(lambda (p e)
(setq e (replace-regexp-in-string "\n$" "" e))
(cond
((and (null my-dired-spawn) (= 9 (process-exit-status p)))
(message "OFF: my-dired-qlmanage (%s) | %s | %s"
(process-exit-status p) p e))
((and my-dired-spawn (= 9 (process-exit-status p)))
(message "OFF/ON: my-dired-qlmanage (%s) | %s | %s"
(process-exit-status p) p e)
(my-dired-kill-spawn))
((= 0 (process-exit-status p))
(message "OFF (mouse clicked): my-dired-qlmanage (%s) | %s | %s"
(process-exit-status p) p e))
(t
(message "ABNORMAL: my-dired-qlmanage (%s) | %s | %s"
(process-exit-status p) p e))))))))
(defun my-dired-kill-spawn ()
"This is essentially a three level incursion,
starting with `my-dired-qlmanage' and then calling `my-dired-kill-spawn' twice."
(interactive)
(let* ((current-node (dired-get-file-for-visit)))
(set-process-sentinel
(start-process "qlmanage" nil "/usr/bin/qlmanage" "-p" current-node)
(lambda (p e)
(setq e (replace-regexp-in-string "\n$" "" e))
(cond
((and (null my-dired-spawn) (= 9 (process-exit-status p)))
(message "OFF: my-dired-kill-spawn (%s) | %s | %s"
(process-exit-status p) p e))
((and my-dired-spawn (= 9 (process-exit-status p)))
(message "OFF/ON: my-dired-kill-spawn (%s) | %s | %s"
(process-exit-status p) p e)
(my-dired-kill-spawn))
((= 0 (process-exit-status p))
(message "OFF (mouse clicked): my-dired-kill-spawn (%s) | %s | %s"
(process-exit-status p) p e))
(t
(message "ABNORMAL: my-dired-kill-spawn (%s) | %s | %s"
(process-exit-status p) p e)))))))
(defun my-dired-previous-line (arg)
(interactive "^p")
(dired-previous-line arg)
(let ((my-dired-spawn t))
(my-dired-kill-last-process-named "qlmanage")))
(defun my-dired-next-line (arg)
(interactive "^p")
(dired-next-line arg)
(let ((my-dired-spawn t))
(my-dired-kill-last-process-named "qlmanage")))
(defun my-dired-quicklook ()
(interactive)
(my-dired-qlmanage))
)
;; エコーエリアの使用を強制的に1行にする
(setq eldoc-echo-area-use-multiline-p nil)
;; C/C++
(add-hook 'c-mode-hook 'eglot-ensure)
(add-hook 'c++-mode-hook 'eglot-ensure)
;; Python
(add-hook 'python-mode-hook #'eglot-ensure)
;; 保存時に自動整形 (eglot)
(add-hook 'python-mode-hook
#'(lambda ()
(add-hook 'before-save-hook
#'eglot-format-buffer nil t)))
;; C/C++
(add-hook 'c-mode-common-hook
#'(lambda ()
(c-set-style "GNU")
(setq c-basic-offset 4) ;; width of indent
(setq fill-column 80)
(setq-default auto-fill-mode t)))
;; recentf
(recentf-mode +1)
(setq recentf-max-saved-items 2000)
;; (setq recentf-auto-save-timer (run-with-idle-timer 30 t 'recentf-save-list))
(defmacro with-suppressed-message (&rest body)
"Suppress new messages temporarily in the echo area and the
`*Messages*' buffer while BODY is evaluated."
(declare (indent 0))
(let ((message-log-max nil))
`(with-temp-message (or (current-message) "") ,@body)))
(setq recentf-auto-save-timer
(run-with-idle-timer 30 t #'(lambda () ;; 30秒ごとに .recentf を保存
(with-suppressed-message (recentf-save-list)))))
(setq recentf-exclude
'(".recentf" "bookmarks" "^/tmp\\.*" ".gz$" "/TAGS$" ".history"))
;; migemo ローマ字入力検索
(setq migemo-command "cmigemo")
(setq migemo-options '("-q" "--emacs"))
(setq migemo-dictionary
"/opt/homebrew/Cellar/cmigemo/20110227/share/migemo/utf-8/migemo-dict")
(setq migemo-user-dictionary nil)
(setq migemo-regex-dictionary nil)
(setq migemo-coding-system 'utf-8-unix)
(autoload 'migemo-toggle-isearch-enable "migemo" nil t)
(define-key isearch-mode-map (kbd "C-e") #'migemo-toggle-isearch-enable)
(with-eval-after-load 'migemo
(migemo-init)
(setq migemo-isearch-enable-p nil)
;; 自動連文節検索
;; https://www.tkl.iis.u-tokyo.ac.jp/~ynaga/tips/elisp_tips.html#auto-ren
(defun my-upcase-at-pos (str pos) ; upcase str at a given pos
(store-substring (copy-sequence str) pos (upcase (aref str pos))))
(defun my-gen-renstr (str &optional index) ; 次単語の先頭を大文字化
(setq index (or index (1- (length str)))) ; 検索文字列の末尾から
(cond ((= index 0) ; 1-depth fallback
(cond ((let ((case-fold-search nil)) (string-match "[^a-z]$" str)) str)
(t (my-gen-renstr (my-upcase-at-pos str (1- (length str)))))))
((and ; 文節の先頭となり得る位置で
(let ((case-fold-search nil))
(string-match "^[a-z]" (substring str index)))
(string-match "^[aiueon]\\(?:[a-mo-z].*\\|n[aiueo].*\\|n\\)$"
(substring str (1- index))))
(save-excursion ; 検索が成功するかどうか検査
(goto-char (point-min))
(migemo-forward (my-upcase-at-pos str index) nil t))
(my-upcase-at-pos str index))
(t (my-gen-renstr str (1- index))))) ; try backward
(defadvice isearch-update (after my-migemo-auto-ren activate)
(when (and (featurep 'migemo) migemo-isearch-enable-p ; migemo が on で,
(eq this-command 'isearch-printing-char) ; 検索文字列を伸ばして
(not isearch-success) ; 検索に失敗し,
(save-excursion ; 残りのバッファを検索しても検索文字列がない場合
(not (funcall
(if isearch-forward 'migemo-backward 'migemo-forward)
isearch-string nil t))))
;; migemo で isearch に失敗したら連文節検索を試みる
(let ((renstr (my-gen-renstr isearch-string)))
(when renstr
(setq isearch-string renstr
isearch-message isearch-string)
(goto-char isearch-opoint) ; 再検索
(isearch-search)))))
)
;; avy カーソル移動の強化
(global-set-key (kbd "C-z ;") #'avy-goto-char)
(global-set-key (kbd "C-c C-;") #'avy-goto-char-2)
(global-set-key (kbd "C-z C-l") #'avy-goto-line)
(define-key isearch-mode-map (kbd "C-;") #'avy-isearch)
(defadvice previous-line (around my-previous-line activate)
(cond ((eq (ad-get-arg 0) 4)
(avy-goto-line 1))
((eq (ad-get-arg 0) 16)
(avy-goto-line 4))
(t
ad-do-it)))
(defadvice avy-goto-line (around my-avy-goto-line activate)
(let ((avy-style 'at-full))
ad-do-it))
;; consult 便利系コマンドの集合体
(global-set-key (kbd "C-x b") #'consult-buffer)
(global-set-key (kbd "C-x 4 b") #'consult-buffer-other-window)
(global-set-key (kbd "C-x 5 b") #'consult-buffer-other-frame)
(global-set-key (kbd "C-x t b") #'consult-buffer-other-tab)
(global-set-key (kbd "C-x r b") #'consult-bookmark)
(global-set-key (kbd "C-z C-n") #'consult-recent-file)
(global-set-key (kbd "M-y") #'consult-yank-pop)
(global-set-key (kbd "M-g g") #'consult-goto-line)
(global-set-key (kbd "M-g i") #'consult-imenu)
;; (global-set-key (kbd "M-s l") #'consult-line) ;; プレビュー付きの行単位検索
(global-set-key (kbd "M-s l") #'consult-line-symbol-at-point) ;; プレビュー付きの行単位検索
(global-set-key (kbd "M-s L") #'consult-line-multi) ;; 複数バッファ串刺し検索
(global-set-key (kbd "M-s r") #'consult-ripgrep) ;; ripgrepによる高速検索 C-uでディレクトリ指定
(define-key isearch-mode-map (kbd "M-e") #'consult-isearch-history)
(define-key isearch-mode-map (kbd "M-s e") #'consult-isearch-history)
(define-key isearch-mode-map (kbd "M-s l") #'consult-line)
(define-key isearch-mode-map (kbd "M-s L") #'consult-line-multi)
(define-key minibuffer-local-map (kbd "M-r") #'consult-history)
;; カーソル下のシンボルを拾ってconsult-line発動
(defun consult-line-symbol-at-point (&optional at-point)
"Consult-line uses things-at-point if set C-u prefix."
(interactive "P")
(if at-point
(consult-line (thing-at-point 'symbol))
(consult-line)))
;; consult-buffer の live preview でシンタックスハイライトさせない
;; 画像プレビューには向いていない
(setq consult-preview-partial-size 0)
;; 0に設定すれば画像やPDFプレビューさせない(バッファを開いていない場合)
(setq consult-preview-partial-chunk 102400)
;; ローマ字入力でconsult-lineを発動する
(defun consult-line-migemo ()
(interactive)
(let ((input (read-string "Input: " nil)))
(consult-line (migemo-get-pattern input))))
;; migemo検索中からでもconsult-line発動
(defun consult-line-migemo-isearch ()
(interactive)
(consult-line (migemo-get-pattern isearch-string)))
(define-key isearch-mode-map (kbd "C-o") #'consult-line-migemo-isearch)
(autoload 'consult-selected "consult-selected" nil t)
(autoload 'consult-line-thing-at-point "consult-thing-at-point" nil t)
;; vertico ミニバッファの入力と補完を強化
(vertico-mode 1)
(vertico-prescient-mode 1) ;; 候補を履歴や頻度を考慮して並び替える
(setq vertico-cycle t)
;; savehist-modeを使ってVerticoの順番を永続化する
(savehist-mode)
;; Enable recursive minibuffers
(setq enable-recursive-minibuffers t)
;; vertico-directory
(define-key vertico-map "DEL" #'vertico-directory-delete-char)
(keymap-set vertico-map "C-l" #'vertico-directory-up)
;; vertico-quick
(keymap-set vertico-map "M-q" #'vertico-quick-insert) ;; avy-likeに候補選択してミニバッファ入力
(keymap-set vertico-map "C-q" #'vertico-quick-exit) ;; avy-likeに候補選択して即時実行
;; marginalia 補完候補のアノテーションを追加
(marginalia-mode 1)
(define-key minibuffer-local-map (kbd "M-A") #'marginalia-cycle)
;; embark
(global-set-key (kbd "C-'") #'embark-act)
(global-set-key (kbd "C-\"") #'embark-dwim)
(with-eval-after-load 'consult
(with-eval-after-load 'embark
(require 'embark-consult)))
;; corfu 補完パッケージ
(global-corfu-mode 1)
(corfu-prescient-mode +1)
(setq corfu-auto nil) ;; Enable auto completion
(setq corfu-cycle t) ;; Enable cycling for `corfu-next/previous'
(setq corfu-quit-at-boundary nil) ;; Never quit at completion boundary ->あいまいマッチしやすい
;; (setq corfu-quit-at-boundary 'separator) ;; seperatorで指定された文字でquitする
;; (setq corfu-quit-no-match 'separator) ;; seperatorで指定された文字はmatchから除外される ->あいまいマッチしやすい
;; (setq corfu-quit-no-match nil) ;; query が match しないとき "no match" 表示
;; (setq corfu-quit-no-match t) ;; query が match しないとき即終了
;; (setq corfu-separator ?\s)
;; Configure if the prompt or first candidate is preselected.
;; - prompt: Always select the prompt.
;; - first: Always select the first candidate.
;; - valid: Only select the prompt if valid and not equal to the first candidate.
;; - directory: Like first, but select the prompt if it is a directory.
;; (setq corfu-preselect 'valid) ;; スペース区切りであいまい入力しても補完候補で補正
;; (setq corfu-preselect 'prompt) ;; 補完開始後に入力したものがそのままバッファに入る
(setq completion-cycle-threshold 3) ;; TAB cycle if there are only few candidates
;; Emacs 28: Hide commands in M-x which do not apply to the current mode.
;; Corfu commands are hidden, since they are not supposed to be used via M-x.
(setq read-extended-command-predicate #'command-completion-default-include-p)
;; Enable indentation+completion using the TAB key.
;; `completion-at-point' is often bound to M-TAB.
;; (setq tab-lways-indent t)
(setq tab-always-indent 'complete)
;; 参考 http://blog.fujimisakari.com/elisp_useful_for_programming/
(defun selected-setup-elisp ()
(require 'selected nil t)
;; 選択した関数のヘルプを表示
(define-key selected-keymap (kbd "f") #'describe-function)
;; 選択した変数のヘルプを表示
(define-key selected-keymap (kbd "v") #'describe-variable)
;; 選択したシンボルのヘルプを表示
(define-key selected-keymap (kbd "y") #'describe-symbol))
(defun selected-setup-common ()
(require 'selected nil t)
(defun region-to-single-quote ()
(interactive)
(quote-formater "'%s'" "^\\(\"\\).*" ".*\\(\"\\)$"))
(defun region-to-double-quote ()
(interactive)
(quote-formater "\"%s\"" "^\\('\\).*" ".*\\('\\)$"))
(defun region-to-bracket ()
(interactive)
(quote-formater "\(%s\)" "^\\(\\[\\).*" ".*\\(\\]\\)$"))
(defun region-to-square-bracket ()
(interactive)
(quote-formater "\[%s\]" "^\\(\(\\).*" ".*\\(\)\\)$"))
(defun region-to-brace ()
(interactive)
(quote-formater "\%s\]" "^\\(\(\\).*" ".*\\(\)\\)$"))
(defun quote-formater (quote-format re-prefix re-suffix)
(if mark-active
(let* ((region-text (buffer-substring-no-properties
(region-beginning) (region-end)))
(replace-func
(lambda (re target-text)
(replace-regexp-in-string re "" target-text nil nil 1)))
(text (funcall replace-func re-suffix
(funcall replace-func re-prefix region-text))))
(delete-region (region-beginning) (region-end))
(insert (format quote-format text)))
(error "Not Region selection")))
;; コメントアウト・アンコメントアウト
(define-key selected-keymap (kbd ";") #'comment-dwim-2)
;; リージョンをシングルクオートで囲う
(define-key selected-keymap (kbd "\'") #'region-to-single-quote)
;; リージョンをダブルクオートで囲う
(define-key selected-keymap (kbd "\"") #'region-to-double-quote)
;; リージョンをブラケット(カッコ)で囲う
(define-key selected-keymap (kbd "(") #'region-to-bracket)
;; リージョンをカギカッコで囲う
(define-key selected-keymap (kbd "[") #'region-to-square-bracket)
;; consult-line
(define-key selected-keymap (kbd "w") #'consult-line-thing-at-point)
;; consultインターフェイスで選択
(define-key selected-keymap (kbd "l") #'consult-selected)
;; リージョンの文字数や単語数をカウント
(define-key selected-keymap (kbd "=") #'count-words-region)
;; 複数カーソルによるマーク
(define-key selected-keymap (kbd "A") #'mc/mark-all-like-this)
(define-key selected-keymap (kbd "n") #'mc/mark-next-like-this)
(define-key selected-keymap (kbd "p") #'mc/mark-previous-like-this)
(define-key selected-keymap (kbd "u") #'mc/unmark-next-like-this)
(define-key selected-keymap (kbd "U") #'mc/unmark-previous-like-this)
(define-key selected-keymap (kbd "s") #'mc/skip-to-next-like-this)
(define-key selected-keymap (kbd "S") #'mc/skip-to-previous-like-this)
;; 同時編集 iedit
;; デフォルトではバッファ全体にカーソルが分身して編集可能になるので、
;; ナローイングを適宜用いる
(define-key selected-keymap (kbd "i") #'iedit-mode))
(add-hook 'emacs-lisp-mode-hook
#'(lambda ()
(selected-setup-common)
(selected-setup-elisp)
(selected-minor-mode 1)))
(add-hook 'prog-mode-hook
#'(lambda ()
(selected-setup-common)
(selected-minor-mode 1)))
;; ポップアップウィンドウの挙動を調整
(shackle-mode 1)
(setq shackle-rules
'(
("*Help*" :align below :select t)
("*quickrun*" :align below :select t)
("*Ibuffer*" :align below :select t)
))
;; Command-tab的にバッファ切り替え
(setq iflipb-wrap-around t)
(setq iflipb-ignore-buffers (list "^[*]"))
;; 切り替え対象をカレントバッファと同一のメジャーモードに限定する
(defun iflipb-major-mode-buffer-list ()
"Returns list of buffers whose major-mode is the same as current buffer's one."
(let ((cur-buf-list (buffer-list (selected-frame)))
(same-major-mode-buflist nil)
(currbuf-major-mode
(buffer-local-value 'major-mode (current-buffer))))
(dolist (buffer cur-buf-list)
(if (eq (buffer-local-value 'major-mode buffer) currbuf-major-mode)
(add-to-list 'same-major-mode-buflist buffer)))
(nreverse same-major-mode-buflist)))
(setq iflipb-buffer-list-function 'iflipb-major-mode-buffer-list)
(defhydra hydra-iflipb (global-map "C-;")
"flip buffer"
("C-n" iflipb-next-buffer "next")
("C-p" iflipb-previous-buffer "prev"))
;; neotree
(setq neo-show-hidden-files t)
(setq neo-hidden-regexp-list '("\\.pyc$" "~$" "^#.*#$" "\\.elc$"))
;; neotree でファイルを新規作成した後、自動的にファイルを開く
(setq neo-create-file-auto-open t)
;; conciseにするとキーバインドをシンプルにする
;; default
;; C-c C-n 作成
;; C-c C-d 削除
;; C-c C-r リネーム
;; C-c C-p コピー
;; concise
;; C ルートディレクトリ変更
;; c 作成
;; + 作成
;; d 削除
;; r リネーム
;; e エンター
(setq neo-keymap-style 'concise)
;; neotree ウィンドウを表示する毎に current file のあるディレクトリを表示する
(setq neo-smart-open t)
;; 幅
(setq neo-window-width 20)
;; 自動リフレッシュ & ディレクトリ自動表示変更
(setq neo-autorefresh t
neo-force-change-root t)
(add-hook 'neotree-mode-hook
#'(lambda ()
(display-line-numbers-mode -1)))
(global-set-key [f6] 'neotree-toggle)
;; HOWM
(setq howm-menu-lang 'ja)
(setq howm-directory "~/.emacs.d/etc/howm")
(setq howm-list-recent-days 7)
(setq howm-view-split-horizontally t)
(autoload 'howm-menu "howm" nil t)
(with-eval-after-load 'howm
(setq howm-template
(concat howm-view-title-header " %title%cursor\n%date\n\n")))
;; key-combo
(defun key-combo-setup ()
(require 'key-combo)
(key-combo-define-global
"C-a" '(back-to-indentation
move-beginning-of-line
beginning-of-buffer key-combo-return))
(key-combo-define-global
"C-e" '(move-end-of-line end-of-buffer key-combo-return))
(setq key-combo-python-mode-hooks '(python-mode-hook))
(setq key-combo-python-default
'(("," . (", " ","))
("+" . (" + " "+"))
("+=" . " += ")
("-" . (" - " "-"))
("-=" . " -= ")
("*" . (" * " "*"))
("*=" . " *= ")
("/" . (" / " " // " "/"))
("/=" . " /= ")
("=" . (" = " " == " "="))
("(" . ("(`!!')" "("))
("\"" . ("\"`!!'\"" "\""))
))
(key-combo-define-hook key-combo-python-mode-hooks
'key-combo-python-load-default
key-combo-python-default)
(setq key-combo-c-mode-hooks '(c-mode-hook))
(setq key-combo-c-mode-default
'(("," . (", " ","))
("=" . (" = " " == " " === " "="))
("=>" . " => ")
("=~" . " =~ ")
("+" . (" + " "++" " += " "+"))
("+=" . " += ")
("-" . (" - " " -= " "-"))
("-=" . " -= ")
(">" . (" > " " => " " >= " ">"))
(">=" . " >= ")
("%" . (" % " "%"))
("!" . (" != " "!"))
("!=" . " != " )
("&" . (" & " " && " "&"))
("&=" . " &= ")
("*" . (" * " "**" "*"))
("*=" . " *= " )
("<" . (" < " " <= " "<"))
("<=" . " <= ")
("|" . (" || " "|"))
("/" . (" / " "/`!!'/" "// "))
("/=" . " /= ")
("/*" . "/* `!!' */")
("{" . ("{`!!'}" "{"))
("\"" . ("\"`!!'\"" "\""))
("'" . ("'`!!''" "'"))
("(" . ("(`!!')" "("))))
(key-combo-define-hook key-combo-c-mode-hooks
'key-combo-c-mode-load-default
key-combo-c-mode-default))
(add-hook 'python-mode-hook
#'(lambda ()
(key-combo-setup)
(key-combo-mode 1)))
(add-hook 'c-mode-hook
#'(lambda ()
(key-combo-setup)
(key-combo-mode 1)))
(add-hook 'emacs-lisp-mode-hook
#'(lambda ()
(key-combo-mode 1)
(key-combo-load-default)))
(add-hook 'eshell-mode-hook
#'(lambda ()
(key-combo-mode -1)))
;; eshell
(defun my-eshell-view-file (file)
"A version of `view-file' which properly respects the eshell prompt."
(interactive "fView file: ")
(unless (file-exists-p file) (error "%s does not exist" file))
(let ((had-a-buf (get-file-buffer file))
(buffer (find-file-noselect file)))
(if (eq (with-current-buffer buffer (get major-mode 'mode-class))
'special)
(progn
(switch-to-buffer buffer)
(message "Not using View mode because the major mode is special"))
(let ((undo-window (list (window-buffer) (window-start)
(+ (window-point)
(length (funcall eshell-prompt-function))))))
(switch-to-buffer buffer)
(view-mode-enter (cons (selected-window) (cons nil undo-window))
'kill-buffer)))))
(defun eshell/less (&rest args)
"Invoke `view-file' on a file. \"less +42 foo\" will go to line 42 in
the buffer for foo."
(while args
(if (string-match "\\`\\+\\([0-9]+\\)\\'" (car args))
(let* ((line (string-to-number (match-string 1 (pop args))))
(file (pop args)))
(my-eshell-view-file file)
(goto-line line))
(my-eshell-view-file (pop args)))))
(defalias 'eshell/more 'eshell/less)
(defun eshell-maybe-bol ()
(interactive)
(let ((p (point)))
(eshell-bol)
(if (= p (point))
(beginning-of-line))))
(add-hook 'eshell-mode-hook
#'(lambda () (define-key eshell-mode-map "\C-a" 'eshell-maybe-bol)))
;; pdf-tools
;; pdf-tools-installで有効化
;; which-key
(which-key-mode 1)
;; ibuffer
;; number of rows
(defun ibuffer-after-init ()
(require 'ibuffer)
(define-ibuffer-column row
(:name "Rows" :inline t)
(format "%5d" (count-lines (point-min) (point-max))))
;; human readable size
(define-ibuffer-column size-h
(:name "Size" :inline t)
(cond
((> (buffer-size) 1000000) (format "%7.1fM" (/ (buffer-size) 1000000.0)))
((> (buffer-size) 1000) (format "%7.1fk" (/ (buffer-size) 1000.0)))
(t (format "%8d" (buffer-size)))))
(setq ibuffer-formats '((mark modified read-only
" " (name 30 40 :left :elide)
" " (size-h 9 -1 :right) ;modified
" " (row 5 -1 :right) ;modified
" " (mode 16 16 :left :elide)
" " filename-and-process)
(mark " " (name 16 -1)
" " filename)))
(setq ibuffer-saved-filter-groups
'(("Default"
("Emacs" (or
(name . "^\\*scratch\\*$")
(name . "^\\*Messages\\*$")))
("Dired" (mode . dired-mode))
("Python" (mode . python-mode))
("Elisp" (mode . emacs-lisp-mode))
)))
)
(add-hook 'after-init-hook #'ibuffer-after-init)
(add-hook 'ibuffer-mode-hook
(lambda ()
(ibuffer-switch-to-saved-filter-groups "Default")))
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(blink-cursor-mode nil)
'(column-number-mode t)
'(package-archives
'(("gnu" . "https://elpa.gnu.org/packages/")
("melpa" . "https://melpa.org/packages/")
("org" . "https://orgmode.org/elpa/")))
'(package-selected-packages
'(cape all-the-icons-nerd-fonts all-the-icons-dired dired-icon dired-collapse dired-narrow dired-sidebar dired-subtree dired-ranger dired-open dired-filter which-key pdf-tools multi-term key-combo hydra comment-dwim-2 affe ace-link howm iedit yaml-mode yasnippet yasnippet-snippets multiple-cursors expand-region embark embark-consult marginalia neotree window-numbering thingopt iflipb shackle selected vline sequential-command smart-newline undo-tree compat dash popup seq transient wgrep python-mode migemo rg mozc-temp mozc-popup mozc corfu prescient corfu-prescient vertico-prescient vertico consult-eglot consult avy solarized-theme))
'(tool-bar-mode nil))
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(default ((t (:family "Ricty Diminished" :foundry "nil" :slant normal :weight regular :height 140 :width normal))))
'(dired-subtree-depth-1-face ((t (:background "#eee8d5"))))
'(dired-subtree-depth-2-face ((t (:background "#eee8d5"))))
'(vline ((t (:background "#eee8d5")))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment