Emacs の設定
はじめに
Debian パッケージがインストールされているならばそれを優先する
:Eating your own dog food - Wikipedia
Emacsに関連するDebianパッケージを幾つかメンテナンスしているので, 可能な限りDebianパッケージを使うことにしています.
leaf.elでEmacs のパッケージの導入と設定を行なう
設定は Org mode で書きたい
以前こんなブログ記事を書きました→ Emacsの設定ファイルをorgで書く
というわけで, 設定は Org Babel で書いています.
本ファイル(README.org
) から,
Makefile 内の以下のスクリプトで ~/init.el
を生成し, byte-compile します.
EMACS ?= emacs
init.el: README.org
$(EMACS) -Q -q --batch --eval \
"(progn \
(require 'ob-tangle) \
(org-babel-tangle-file \"$<\" \"$@\" \"emacs-lisp\"))"
$(EMACS) -q -l init.el --batch --eval '(kill-emacs)'
%.elc: %.el
$(EMACS) -q -l init.el -batch -f batch-byte-compile $<
設定ファイルのヘッダ
出力される init.el
用のヘッダは以下の通り.
lexsical-binding
を有効にしておきます.
;; -*- lexical-binding: nil -*-
起動の高速化
この辺は Emacs の起動時間を""詰める"" を参考に.
設定は early-init.el
に移動した方が良いのかもしれないかな.
Emacs Profiler
起動の高速化を検証するために, 必要に応じて有効に.
;; (require 'profiler)
;; (profiler-start 'cpu)
Magic File Name を一時的に無効化
これだけで 0.2秒縮まった. これは知見である.
(defconst my:saved-file-name-handler-alist file-name-handler-alist)
(setq file-name-handler-alist nil)
(add-hook 'emacs-startup-hook
(lambda ()
(setq file-name-handler-alist my:saved-file-name-handler-alist)))
GC の設定
起動時に garbage collection を発生させない様にする.
メモリ喰いな拡張を入れている場合には,
安易に gc-cons-threshold
を上げるのは考えものである.
「gc が走る→大きな領域を掃除するのでその間 emacs が止まる」
という事を頻繁に経験することになるだろう.
とはいえ, デフォルト値のままだと
起動時に結構 garbage-collect が走って遅くなるので,
起動時は most-positive-fixnum
にしておいて,
起動後に emacs-startup-hook
で default に戻すようにしてみた.
ついでに idle-timer
で入力が無い時に GC を走らせることに.
(defconst my:default-gc-cons-threshold gc-cons-threshold)
(setq gc-cons-threshold most-positive-fixnum)
;; Run GC every 60 seconds if emacs is idle.
(run-with-idle-timer 60.0 t #'garbage-collect)
(add-hook 'emacs-startup-hook
(lambda ()
(setq gc-cons-threshold my:default-gc-cons-threshold)))
early-init.el
Emacs >= 27 からの機能だが, いまいち使い方がわからん.
(push '(vertical-scroll-bars . nil) default-frame-alist)
(push '(menu-bar-lines . nil) default-frame-alist)
(push '(tool-bar-lines . nil) default-frame-alist)
(push '(scroll-bar-mode . nil) default-frame-alist)
(push '(blink-cursor-mode . nil) default-frame-alist)
(push '(column-number-mode . nil) default-frame-alist)
(setq load-prefer-newer noninteractive)
(setq frame-inhibit-implied-resize t)
(setq site-run-file nil)
;; (Setq window-divider-default-right-width 3)
(setq package-enable-at-startup nil)
(provide 'early-init)
;;; early-init.el ends here
ディレクトリ構成の修正
分割した設定ファイル群やパッケージでinstallしたパッケージ
の置き場所は user-emacs-directory
以下にまとめています。
ディレクトリ構成は以下のようにしました:
~/.emacs.d/ |-- Makefile ← byte-compile 用の rule |-- README.org ← 本ファイル.`org-babel-tangle' で init.el を生成 |-- pkg | |-- elpa/ ← package.el で導入したパッケージが置かれる場所 | `-- el-get/ ← el-get で導入したパッケージが置かれる場所 `-- share/ ← (基本的に)参照するだけの資源置き場所 ~/.cache/emacs ← 一次ファイルの置き場所
上記ディレクトリ構成を設定ファイルで使用するために ディレクトリ配置を宣言しておきます。
(when load-file-name
(setq user-emacs-directory
(expand-file-name (file-name-directory load-file-name))))
(defconst my:d:share
(expand-file-name "share/" user-emacs-directory))
(defconst my:d:tmp
(expand-file-name ".cache/emacs/" (getenv "HOME")))
(unless (file-directory-p my:d:tmp)
(make-directory my:d:tmp))
(defconst my:d:pkg:elpa
(expand-file-name "pkg/elpa" user-emacs-directory))
(defconst my:d:pkg:elget
(expand-file-name "pkg/el-get" user-emacs-directory))
その他, 良く使うディレクトリもここで設定しておきます.
(defconst my:d:nextcloud (concat (getenv "HOME") "/Nextcloud"))
(defconst my:d:org (expand-file-name "org" my:d:nextcloud))
Byte-Compile 時の Common Lisp の読み込み
幾つかの関数で Common-Lisp
的挙動が期待されているので,
cl-lib
を読み込んでおきます.
(eval-when-compile (require 'cl-lib nil t))
ついでに Emacs 27 以降は cl が読み込まれていると `Package cl is deprecated' が表示されるので, これを止めておく.
(setq byte-compile-warnings '(not cl-functions obsolete))
Package 関連: package.el, leaf.el, el-get
leaf.elのおかげで, 無いと途方に暮れるパッケージ以外のインストールは無視できるようになります.
package.el
パッケージは基本的に package.el
で導入するので, 先ずはその設定.
;; elpa/gnutls workaround
(eval-and-compile
(when (version<= emacs-version "26.2")
(setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3"))
(custom-set-variables
'(package-archives '(("gnu" . "https://elpa.gnu.org/packages/")
("melpa" . "https://melpa.org/packages/")
("org" . "https://orgmode.org/elpa/")
))
'(package-gnupghome-dir (expand-file-name ".gnupg" (getenv "HOME")))
'(package-user-dir my:d:pkg:elpa))
)
(eval-when-compile
(unless (file-exists-p (expand-file-name "bootstrap-stamp" my:d:tmp))
(package-refresh-contents)
(with-temp-buffer
(write-file (expand-file-name "bootstrap-stamp" my:d:tmp)))
))
(package-initialize)
leaf.el
個々のパッケージの設定にはleaf.elを利用します. 自分で修正した版やオリジナル版を別の場所から持ってくる場合は leaf.elからel-getを呼び出します.
(unless (package-installed-p 'leaf)
(package-refresh-contents)
(package-install 'leaf t))
;; (require 'leaf nil 'noerror)
;; (defvar leaf--load-file-name nil)
(leaf leaf-keywords
:ensure t
:init
(leaf blackout :ensure t)
(leaf el-get
:ensure t
:preface
(defconst el-get-dir my:d:pkg:elget) ;; override el-get default
:custom ((el-get-notify-type . 'message)
(el-get-git-shallow-clone . t))
)
)
(leaf-keywords-init)
exec-path-from-shell
: 環境変数の読み込み
shell(zsh)で設定した PATH
などの環境変数をEmacsに引き継ぐために
purcell/exec-path-from-shell を使います.
今の所
DEBEMAIL
DEBFULLNAME
GPG_AGENT_INFO
GPG_KEY_ID
PASSWORD_STORE_DIR
PATH
SHELL
SKKSERVER
TEXMFHOME
WSL_DISTRO_NAME
http_proxy
を読み込んでいます(多いな…).
(leaf exec-path-from-shell
:ensure t
:defun (exec-path-from-shell-initialize)
:custom
((exec-path-from-shell-check-startup-files . nil)
(exec-path-from-shell-arguments . nil)
(exec-path-from-shell-variables
. '(
"DEBEMAIL"
"DEBFULLNAME"
"GPG_AGENT_INFO"
"GPG_KEY_ID"
"PASSWORD_STORE_DIR"
"PATH"
"SHELL"
"SKKSERVER"
"TEXMFHOME"
"WSL_DISTRO_NAME"
"http_proxy"
)))
:config
(exec-path-from-shell-initialize)
(setq user-full-name (concat (getenv "DEBFULLNAME"))
user-mail-address (concat (getenv "DEBEMAIL")))
(defconst my:d:password-store
(if (getenv "PASSWORD_STORE_DIR")
(expand-file-name (concat "Emacs/" (system-name))
(getenv "PASSWORD_STORE_DIR")) ""))
)
認証関連: plstore
, password-store
など
-
leaf-plstore
でplstore
が使えるようになったので, その設定をしておく. -
auth-password-store
で auth-source としてpassword-store
を使う.
といった事をしている.
(leaf *authentication
:if (and (getenv "GPG_KEY_ID")
(file-directory-p my:d:password-store))
:init
(setq leaf-default-plstore
(plstore-open
(expand-file-name "plstore.plist" my:d:password-store)))
(add-to-list 'vc-directory-exclusion-list
(expand-file-name my:d:password-store))
(leaf auth-source
:custom
`((auth-source-gpg-encrypt-to . '(getenv "GPG_KEY_ID"))
;; (auth-sources
;; . ,(expand-file-name "authinfo.gpg" my:d:password-store))
)
)
(leaf password-store :ensure t)
(leaf auth-source-pass :ensure t)
(leaf plstore
:custom
`((plstore-secret-keys . 'silent)
(plstore-encrypt-to . ,(getenv "GPG_KEY_ID")))
)
)
独自関数
細かい独自関数, など.
ファイル名を minibuffer におさまる様に整形
zsh prompt風味.
;;;###autoload
(defun my:shorten-file-path (fpath max-length)
"Show up to `max-length' characters of a directory name `fpath' like zsh"
(let* ((path (reverse (split-string (abbreviate-file-name fpath) "/")))
(output "")
(top (mapconcat 'identity (reverse (last path 3)) "/"))
(vmax (- max-length 4 (length top)))
(path (butlast path 3))
)
(while (and path
(and (< (length output) vmax)
(< (length (concat "/" (car path) output)) vmax)))
(setq output (concat "/" (car path) output))
(setq path (cdr path)))
;; 省略
(when path
(setq output (concat "/..." output)))
(format "%s%s" top output)))
空になったファイルを尋ねずに自動削除
ゴミが残らないし, 地味に便利.
(leaf *delete-file-if-no-contents
:preface
(defun my:delete-file-if-no-contents ()
(when (and (buffer-file-name (current-buffer))
(= (point-min) (point-max)))
(delete-file
(buffer-file-name (current-buffer)))))
:hook
(after-save-hook . my:delete-file-if-no-contents)
)
scratch を殺さない. 消したら再生成
…元ネタがどこだったのか忘れてしまった…
(leaf *keepscratchbuffer
:preface
(defun my:make-scratch (&optional arg)
" *scratch* を作成して buffer-list に放り込む."
(interactive)
(progn
(set-buffer (get-buffer-create "*scratch*"))
(funcall initial-major-mode)
(erase-buffer)
(when (and initial-scratch-message (not inhibit-startup-message))
(insert initial-scratch-message))
(or arg
(progn
(setq arg 0)
(switch-to-buffer "*scratch*")))
(cond ((= arg 0) (message "*scratch* is cleared up."))
((= arg 1) (message "another *scratch* is created")))))
(defun my:buffer-name-list ()
"buffer 一覧の取得"
(mapcar (function buffer-name) (buffer-list)))
;;
:hook
((kill-buffer-query-functions
. (lambda ()
(if (string= "*scratch*" (buffer-name))
(progn (my:make-scratch 0) nil)
t)))
(after-save-hook
. (lambda ()
(unless (member "*scratch*" (my:buffer-name-list))
(my:make-scratch 1)))))
)
SOMEDAY 行末の無駄な空白/改行を削除する [/]
@see 無駄な行末の空白を削除する(Emacs Advent Calendar jp:2010)
ただし, RD や Markdown だと空白行に意味があったりするので, 必要に応じて拡張子で判断して外している.
(leaf *trailing-white-space
:preface
(defvar my:delete-trailing-whitespace-exclude-suffix
(list "\\.rd$" "\\.md$" "\\.rbt$" "\\.rab$"))
(defun my:delete-trailing-whitespace ()
(interactive)
(eval-when-compile (require 'cl-lib))
(cond
((equal nil
(cl-loop for pattern in my:delete-trailing-whitespace-exclude-suffix
thereis (string-match pattern buffer-file-name)))
(delete-trailing-whitespace))))
:hook
(before-save-hook . my:delete-trailing-whitespace)
)
-
[ ]
cl 依存の書き換え?
ターミナルで C-M-
を打つために
詳細は
Using C-M-% to do a query-replace-regexp in Emacs running in Mac terminal
を参照のこと. terminal では C-%
(つまり Control-Shift-5
)が入力できない, という話.
代わりに C-x @
を C-M-
に解釈させるように設定しておく.
; cargo cult adaptation of event-apply-control-modifier
(defun my:event-apply-control-meta-modifiers (ignore-prompt)
(vector
(event-apply-modifier (event-apply-modifier (read-event)
'control 26 "C-")
'meta 27 "M-")))
(define-key function-key-map (kbd "C-x @") 'my:event-apply-control-meta-modifiers)
言語の設定
最近のEmacsはlocaleから文字コードを自動判別するらしいので, 以前良く設定していた以下は不要らしいですね(ホントかな…?)。
(set-language-environment "Japanese")
(prefer-coding-system 'utf-8)
(set-file-name-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-default 'buffer-file-coding-system 'utf-8)
なお, m17n.org の消滅によって上記設定に関する情報の参照元が消えた。 適切な参照元はどこだろう…?
cp5022x.el
Emacs23 から内部が Unicode ベースになっています。
しかし文字コードの変換はGNU libcのiconvをベースにしているため,
機種依存文字を含む文字コードの変換をうまく行なえません。
そこで言語設定前に cp5022x.el
をインストールすることにしています。
(leaf cp5022x
:ensure t
:require t
:config
(set-charset-priority 'ascii 'japanese-jisx0208 'latin-jisx0201
'katakana-jisx0201 'iso-8859-1 'unicode)
(set-coding-system-priority 'utf-8 'euc-jp 'iso-2022-jp 'cp932)
)
主にEmacs本体, および同梱されている拡張に関する設定
終了時に custom.el
を消す
設定ファイルに極力移す.
(leaf cus-edit
:preface
(setq custom-file (expand-file-name "custom.el" my:d:tmp))
:custom
`((custom-file . ,(expand-file-name "custom.el" my:d:tmp)))
:hook
`((kill-emacs-hook . (lambda ()
(if (file-exists-p custom-file)
(delete-file custom-file)))))
)
customize
で設定していたアレコレ
custom.el
にある設定は極力こちらに移すようにしている.
- 大抵の場合ターミナル内で
-nw
として起動するし, メニューは触ったことないので使わないので, フレーム, ツールバー等を非表示にする. -
.elc
と.el
の timestamp を比較し, 新しい方を読み込む (load-prefer-newer
は Emacs >= 24.4 から). - yes or no を y or n に
他にもイロイロと. 設定が増えてきたら分ける.
(leaf cus-start
:custom
`(
;; 表示
(ring-bell-function . 'ignore) ; ベル無効化
;; 編集
(tab-width . 4) ;; tab 幅 4
(indent-tabs-mode . nil) ;; tab ではインデントしない
(fill-column . 72) ;; RFC2822 風味
(truncate-lines . nil) ;; 折り返し無し
(truncate-partial-width-windows . nil)
(paragraph-start . '"^\\([ ・○<\t\n\f]\\|(?[0-9a-zA-Z]+)\\)")
(auto-fill-mode . nil)
(next-line-add-newlines . nil) ;; バッファ終端で newline を入れない
(read-file-name-completion-ignore-case . t) ; 大文字小文字区別無し
(save-abbrevs . 'silent)
;; backup
(auto-save-list-file-prefix . ,(expand-file-name ".saves-" my:d:tmp))
(auto-save-default . t)
(auto-save-timeout . 15)
(auto-save-interval . 60)
(make-backup-files . t)
(backup-by-copying . t) ;; symlink は使わない
(backup-directory-alist . '(("." . ,my:d:tmp)))
(auto-save-file-name-transforms . '((".*" ,my:d:tmp t)))
(version-control . nil)
(kept-new-versions . 2)
(kept-old-versions . 2)
(delete-old-versions . t)
(delete-auto-save-files . t)
;; undo/redo - 数字に根拠無し
(undo-limit . 200000)
(undo-strong-limit . 260000)
(history-length . t) ;; 無制限(の筈)
;; (save-silently . t)
;;
(safe-local-variable-values
. '((org-link-file-path-type . absolute)))
)
:config
(when (boundp 'load-prefer-newer)
(setq load-prefer-newer t))
;; yes or no を y or n に
(fset 'yes-or-no-p 'y-or-n-p)
)
startup
: 起動は静かに
(leaf startup
:custom
((inhibit-startup-screen . t)
(inhibit-startup-message . t)
(inhibit-startup-echo-area-message . t)
(initial-scratch-message . nil)
)
)
hl-mode
: 現在行のハイライト
(leaf hl-line
:hook
(emacs-startup-hook . global-hl-line-mode)
)
選択リージョンに色付け
(leaf simple
:hook
(emacs-startup-hook . transient-mark-mode)
)
show-paren-mode
: 対応する括弧を強調表示
(leaf paren
:custom
((show-paren-style . 'mixed))
:hook
(emacs-startup-hook . show-paren-mode)
)
linum-mode
: 行番号表示
必要に応じて有効にするので, 基本使わない.
通常はモードラインに行番号や桁番号を表示しないようする.
ついでに linum-mode
を有効にした場合の桁表示を 5 桁に.
(leaf line-number-mode
:custom
((linum-format . "%5d ")
(line-number-mode . nil))
)
byte-compile 関連
- debug は表示しない: 必要に応じて t に変更する
- Compile-Log の非表示: ほとんど見ないし.
- Warning の抑制: これもほとんど見ないし.
他にも増えそうだが
(eval-and-compile
(leaf bytecomp
:custom
((byte-compile-warnings . '(not
obsolete
free-vars
unresolved
callargs
redefine
noruntime
cl-functions
interactive-only
make-local))
(debug-on-error . nil))
:config
(let ((win (get-buffer-window "*Compile-Log*")))
(when win (delete-window win)))
)
)
autorevert
: ファイルが変更されたら再読み込み
(leaf autorevert
:custom
((auto-revert-interval . 0.1))
:hook
(emacs-startup-hook . global-auto-revert-mode)
)
savehist
: 変更履歴を保存
(leaf savehist
:custom
`((savehist-file
. ,(expand-file-name "history" my:d:tmp)))
:hook
((after-init-hook . savehist-mode))
)
ファイル, デイレクトリ整理
~/.emacs.d/
以下にファイルが転がるのがなんか嫌なので,
気がつく度に設定している.
(leaf *change-default-file-location
:custom
`(;; url
(url-configuration-directory
. ,(expand-file-name "url" my:d:tmp))
;; nsm
(nsm-settings-file
. ,(expand-file-name "nsm.data" my:d:tmp))
;; bookmark
(bookmark-default-file
. ,(expand-file-name "bookmarks" my:d:tmp))
;; eshell
(eshell-directory-name
. ,(expand-file-name "eshell" my:d:tmp))
)
)
他にもイロイロありそう.
bookmark
はちゃんと使いこなしたい所ではあるが.
eldoc
: emacs-lisp document
minibuffer では eldoc にお黙り頂く。
(leaf eldoc
:hook (emacs-lisp-mode-hook . turn-on-eldoc-mode)
:blackout t
:preface
(defun my:shutup-eldoc-message (f &optional string)
(unless (active-minibuffer-window)
(funcall f string)))
:advice
(:around eldoc-message
my:shutup-eldoc-message)
)
midnight
: 一定期間使用しなかった buffer を自動削除
(leaf midnight
:custom
((clean-buffer-list-delay-general . 1))
:hook
(emacs-startup-hook . midnight-mode))
uniquify
: モードラインのファイル名にディレクトリも表示する
(leaf uniquify
:custom
((uniquify-buffer-name-style . 'post-forward-angle-brackets)
(uniquify-min-dir-content . 1))
)
whitespace
: 空白の強調表示
背景も変えようかなぁ…
(leaf whitespace
:blackout ((global-whitespace-mode . "")
(whitespace-mode . ""))
:hook (after-init-hook . global-whitespace-mode)
:custom
((whitespace-line-column . 72)
(whitespace-style
. '(face ; faceを使う
trailing ; 行末の空白を対象.
tabs ; tab
spaces ; space
))
(whitespace-display-mappings . '((space-mark ?\u3000 [?\□])
(tab-mark ?\t [?\u00BB ?\t] [?\\ ?\t])))
(whitespace-space-regexp . "\\(\u3000+\\)")
(whitespace-global-modes . '(not eww-mode
term-mode
eshell-mode
org-agenda-mode
calendar-mode))
)
)
saveplace
: 前回の修正位置を記憶する.
記憶の保存先を ~/.emacs.d/tmp/emacs-places
に変更.
(leaf save-place
:custom
`((save-place . t)
(save-place-file
. ,(expand-file-name "emacs-places" my:d:tmp))
)
:hook (emacs-startup-hook . save-place-mode)
:config
(setq save-place-ingore-files-regexp
(format "\\(%s\\)\\|\\(%s\\)"
save-place-ignore-files-regexp
tramp-file-name-regexp))
)
time-stamp
: 保存時に timestamp を自動更新
デフォルトではいろいろと衝突したので
更新文字列を変更し, $Lastupdate: 2
($は半角) があったら
timestamp を更新する様にした.
(leaf time-stamp
:hook (before-save-hook . time-stamp)
:custom
((time-stamp-active . t)
(time-stamp-line-limit . 10)
(time-stamp-start . "$Lastupdate: 2")
(time-stamp-end . "\\$")
(time-stamp-format . "%Y-%02m-%02d %02H:%02M:%02S")
)
)
モード独自の設定(例えば Org とか)に関しては別途.
tramp
: ssh 越しにファイルを編集
(leaf tramp
:preface
(setq tramp-persistency-file-name (expand-file-name "tramp" my:d:tmp))
:custom
`((tramp-persistency-file-name
. ,(expand-file-name "tramp" my:d:tmp))
(tramp-completion-reread-directory-timeout . nil)
)
:hook
(kill-emacs-hook
. (lambda ()
(if (file-exists-p tramp-persistency-file-name)
(delete-file tramp-persistency-file-name))))
)
browse-url
ブラウザ呼び出しは xdg-open/open
に丸投げ.
(leaf browse-url
:require t
:bind ("C-c C-j" . browse-url-at-point)
:defer-config
(cond ((executable-find "xdg-open")
(setq browse-url-browser-function 'browse-url-xdg-open
browse-url-secondary-browser-function 'browse-url-xdg-open))
((eq system-type 'darwin)
(setq browse-url-browser-function 'browse-url-default-macosx-browser
browse-url-secondary-browser-function 'browse-url-default-macosx-browser))
(t
;; (setq browse-url-browser-function 'w3m-browse-url)
(setq browse-url-browser-function 'eww-browse-url)
))
)
server
: Emacs server
(leaf server
:commands (server-running-p)
:init
(defun my:new-client-frame ()
"Create new GUI emacsclient"
(interactive)
(make-frame-on-display (getenv "DISPLAY")))
:hook
(emacs-startup-hook . (lambda ()
(unless (server-running-p)
(server-start))))
)
buffer の印刷
(leaf ps-mule
:custom
((ps-multibyte-buffer . 'non-latin-printer))
:config
(defalias 'ps-mule-header-string-charset 'ignore)
)
tab-bar-mode
: Emacsの「tab」
Emacs27から同梱された tab-bar-mode
に elscreen から乗り換えた.
手癖で "C-o" を prefix で使いたいので, その設定をしていたり.
(leaf tab-bar-mode
:init
(defvar my:ctrl-o-map (make-sparse-keymap)
"My original keymap binded to C-o.")
(defalias 'my:ctrl-o-prefix my:ctrl-o-map)
(define-key global-map (kbd "C-o") 'my:ctrl-o-prefix)
(define-key my:ctrl-o-map (kbd "c") 'tab-new)
(define-key my:ctrl-o-map (kbd "C-c") 'tab-new)
(define-key my:ctrl-o-map (kbd "k") 'tab-close)
(define-key my:ctrl-o-map (kbd "C-k") 'tab-close)
(define-key my:ctrl-o-map (kbd "n") 'tab-next)
(define-key my:ctrl-o-map (kbd "C-n") 'tab-next)
(define-key my:ctrl-o-map (kbd "p") 'tab-previous)
(define-key my:ctrl-o-map (kbd "C-p") 'tab-previous)
;;
(defun my:tab-bar-tab-name-truncated ()
"Custom: Generate tab name from the buffer of the selected window."
(let ((tab-name (buffer-name (window-buffer (minibuffer-selected-window))))
(ellipsis (cond
(tab-bar-tab-name-ellipsis)
((char-displayable-p ?…) "…")
("..."))))
(if (< (length tab-name) tab-bar-tab-name-truncated-max)
(format "%-12s" tab-name)
(propertize (truncate-string-to-width
tab-name tab-bar-tab-name-truncated-max nil nil
ellipsis)
'help-echo tab-name))))
:custom
((tab-bar-close-button-show . nil)
(tab-bar-close-last-tab-choice . nil)
(tab-bar-close-tab-select . 'left)
(tab-bar-history-mode . nil)
(tab-bar-new-tab-choice . "*scratch*")
(tab-bar-new-button-show . nil)
(tab-bar-tab-name-function . 'my:tab-bar-tab-name-truncated)
(tab-bar-tab-name-truncated-max . 12)
(tab-bar-separator . "")
)
:config
(tab-bar-mode +1)
)
beacon
: buffer 切り替え時の行の強調表示
(leaf beacon
:ensure t
:disabled t
:custom
`((beacon-color . "#aa3400")
;; (beacon-size . 64)
(beacon-blink-when-focused . t)
)
:custom-face
`((beacon-fallback-background . '((t (:background "#556b2f")))))
:config
(beacon-mode 1)
)
recentf
: 最近使ったファイル履歴の保管
結局履歴を貯める設定をしている事になっている. ディレクトリの履歴も取れるので recentf-ext を入れておく
(leaf recentf
:defun
(recentf-save-list recentf-cleanup)
:preface
(leaf shut-up
:ensure t
:init
(defvar shut-up-ignore t))
;;
(defun my:recentf-save-list-silence ()
"Shut up"
(interactive)
(let ((message-log-max nil))
(shut-up (recentf-save-list)))
(message ""))
;;
(defun my:recentf-cleanup-silence ()
"Shut up"
(interactive)
(let ((message-log-max nil))
(shut-up (recentf-cleanup)))
(message ""))
;;
:init
(leaf recentf-ext :ensure t)
:hook
((after-init-hook . recentf-mode)
(focus-out-hook . my:recentf-save-list-silence)
(focus-out-hook . my:recentf-cleanup-silence))
:custom
`((recentf-save-file . ,(expand-file-name "recentf" my:d:tmp))
(recentf-max-saved-items . 2000)
(recentf-auto-cleanup . 'never)
(recentf-exclude . '(".recentf"
"^/tmp\\.*"
"^/private\\.*"
"^/var/folders\\.*"
"/TAGS$"
"\\.*草稿\\.*"
"^#\\.*"
"^/home/uwabami/.mozilla/\\.*"
"^/home/uwabami/.emacs.d/tmp/\\.*"
"^/home/uwabami/.dotfiles/Emacs/tmp/\\.*"
"^/[^/:]+:"
"bookmarks"
"org-recent-headings.dat"
"^/mnt/c/\\.*"
"\\.*COMMIT_EDITMSG$"
".*-autoloads.el$"
"^/home/uwabami/.emacs.d/pkg/\\.*"
)))
)
all-the-icons-in-terminal
: ターミナルでもicon fontを使いたい。
all-the-icons.elのデータを修正して, icons in terminalを修正した 自作フォントのデータを読みに行くようにしてみました。
(leaf all-the-icons
:ensure t
:init (leaf memoize :ensure t)
:require t
:custom
((all-the-icons-scale-factor . 0.9)
(all-the-icons-default-adjust . 0.0))
)
(leaf all-the-icons-in-terminal
:el-get (all-the-icons-in-terminal
:type github
:pkgname "uwabami/isfit-plus")
:after all-the-icons
:require t
:config
(add-to-list 'all-the-icons-mode-icon-alist
'(f90-mode all-the-icons-faicon "facebook")) ;; facebook!?
(add-to-list 'all-the-icons-mode-icon-alist
'(wl-folder-mode all-the-icons-faicon "folder-o" ))
(add-to-list 'all-the-icons-mode-icon-alist
'(wl-summary-mode all-the-icons-faicon "folder-open-o"))
(add-to-list 'all-the-icons-mode-icon-alist
'(wl-draft-mode all-the-icons-material "drafts"))
(add-to-list 'all-the-icons-mode-icon-alist
'(mime-view-mode all-the-icons-faicon "envelope-o"))
)
SOMEDAY East Asian Ambiguos 対応 [0/1]
East Asian Ambiguosを2文字幅にして, ついでに CJK 以外の East Asian Ambiguosと絵文字も2文字幅にするようにしています。 拙作の修正ロケールはこちら: https://github.com/uwabami/locale-eaw-emoji
(leaf locale-eaw-emoji
:el-get uwabami/locale-eaw-emoji
:after all-the-icons-in-terminal
:require t
:config
;; (eaw-half-emoji-fullwidth)
(eaw-and-emoji-fullwidth)
)
-
[ ]
最近, EAWは一文字幅強制の方が良いかなぁ, とか悩み中.
macOS対応
最近良く触る様になったので設定している。
まあ, イマイチ慣れない訳ですけれど
(leaf *mac-encoding
:if (eq system-type 'darwin)
(leaf ucs-normalize
:require t
:defvar (mac-pass-control-to-system ns-command-modifier ns-alternate-modifier)
:config
(set-file-name-coding-system 'utf-8-hfs)
(setq locale-coding-system 'utf-8-hfs)
(setq mac-pass-control-to-system t ;; Ctrl を Mac から奪い取る
ns-command-modifier 'meta ;; Cmd と Option を逆にする
ns-alternate-modifier 'super)
(global-set-key [ns-drag-file] 'ns-find-file)
)
)
Windows(WSL2)対応
(leaf *wsl2-path
:if (getenv "WSL_DISTRO_NAME")
:preface
(defun set-drvfs-alist ()
(interactive)
(setq drvfs-alist
(mapcar
(lambda (x)
(when (string-match "\\(.*\\)|\\(.*?\\)/?$" x)
(cons (match-string 1 x) (match-string 2 x))))
(split-string (concat
;; //wsl$ パス情報の追加
(when (or (not (string-match "Microsoft" (shell-command-to-string "uname -v")))
(>= (string-to-number (nth 1 (split-string operating-system-release "-"))) 18362))
(concat "/|" (shell-command-to-string "wslpath -m /")))
(shell-command-to-string
"mount | grep -E ' type (9p|drvfs) ' | grep -v '^tools on /init type 9p' | sed -r 's/(.*) on (.*) type (9p|drvfs) .*/\\2\\|\\1/' | sed 's!\\\\!/!g'"))
"\n" t))))
;;
(defconst windows-path-style-regexp "\\`\\(.*/\\)?\\([a-zA-Z]:\\\\.*\\|[a-zA-Z]:/.*\\|\\\\\\\\.*\\|//.*\\)")
;;
(defun windows-path-convert-file-name (name)
(setq name (replace-regexp-in-string windows-path-style-regexp "\\2" name t nil))
(setq name (replace-regexp-in-string "\\\\" "/" name))
(let ((case-fold-search t))
(cl-loop for (mountpoint . source) in drvfs-alist
if (string-match (concat "^\\(" (regexp-quote source) "\\)\\($\\|/\\)") name)
return (replace-regexp-in-string "^//" "/" (replace-match mountpoint t t name 1))
finally return name)))
;;
(defun windows-path-run-real-handler (operation args)
"Run OPERATION with ARGS."
(let ((inhibit-file-name-handlers
(cons 'windows-path-map-drive-hook-function
(and (eq inhibit-file-name-operation operation)
inhibit-file-name-handlers)))
(inhibit-file-name-operation operation))
(apply operation args)))
;;
(defun windows-path-map-drive-hook-function (operation name &rest args)
"Run OPERATION on cygwin NAME with ARGS."
(windows-path-run-real-handler
operation
(cons (windows-path-convert-file-name name)
(if (stringp (car args))
(cons (windows-path-convert-file-name (car args))
(cdr args))
args))))
:hook
(after-init-hook
. (lambda ()
(progn
(set-drvfs-alist)
(add-to-list 'my:saved-file-name-handler-alist
(cons windows-path-style-regexp
'windows-path-map-drive-hook-function)))))
)
カレンダー設定
表示の更新と japanese-holidays
による日本の休日の追加
(leaf calendar
:custom
(;; 祝日をカレンダーに表示
(mark-holidays-in-calendar . t)
;; 月と曜日の表示調整
(calendar-month-name-array . ["01" "02" "03" "04" "05" "06"
"07" "08" "09" "10" "11" "12" ])
(calendar-day-name-array . ["日" "月" "火" "水" "木" "金" "土"])
(calendar-day-header-array . ["日" "月" "火" "水" "木" "金" "土"])
;; 日曜開始
(calendar-week-start-day . 0))
:config
(with-eval-after-load 'calendar
(leaf japanese-holidays
:ensure t
:custom
((japanese-holiday-weekend . '(0 6))
(japanese-holiday-weekend-marker . '(holiday ;; 日
nil ;; 月
nil ;; 火
nil ;; 水
nil ;; 木
nil ;; 金
japanese-holiday-saturday)))
:hook
((calendar-today-visible-hook . japanese-holiday-mark-weekend)
(calendar-today-invisible-hook . japanese-holiday-mark-weekend)
(calendar-today-visible-hook . calendar-mark-today))
:config
(setq calendar-holidays (append japanese-holidays))
)
)
)
キーバインドの設定
既に手癖になってしまっているアレコレ.
特に [home]
と [end]
は無いと途方に暮れます.
(leaf-keys (("C-h" . backward-delete-char)
("C-c M-a" . align-regexp)
("C-c ;" . comment-region)
("C-c M-;" . uncomment-region)
("C-/" . undo)
("C-c M-r" . replace-regexp)
("C-c r" . replace-string)
("<home>" . beginning-of-buffer)
("<end>" . end-of-buffer)
("C-c M-l" . toggle-truncate-lines)))
migemo
: インクリメンタル検索
無いと途方に暮れる.
(leaf migemo
:if (executable-find "cmigemo")
:ensure t
;; :require t
:custom
'((migemo-user-dictionary . nil)
(migemo-regex-dictionary . nil)
(migemo-options . '("-q" "--emacs"))
(migemo-command . "cmigemo")
(migemo-coding-system . 'utf-8-unix))
:init
(cond
((and (eq system-type 'darwin)
(file-directory-p "/usr/local/share/migemo/utf-8/"))
(setq migemo-dictionary "/usr/local/share/migemo/utf-8/migemo-dict"))
(t
(setq migemo-dictionary "/usr/share/cmigemo/utf-8/migemo-dict")))
:hook
(after-init-hook . migemo-init)
)
emacs-w3m
:
(leaf emacs-w3m
:if (executable-find "w3m")
;;:el-get (emacs-w3m
;; :type github
;; :pkgname "emacs-w3m/emacs-w3m"
;; :build `(("autoconf")
;; ("./configure" ,(format "--with-emacs=%s" el-get-emacs))
;; ("make"))
;; :info "doc")
:load-path
`(,(expand-file-name "emacs-w3m/shimbun" my:d:pkg:elget))
)
SOMEDAY eww
: 内蔵ブラウザ [0/3]
リンクを簡単に辿る(Hit-a-Hint) のために ace-link
も入れておく
(leaf eww
:preface
(unless (file-directory-p (expand-file-name "eww" my:d:tmp))
(make-directory (expand-file-name "eww" my:d:tmp)))
:init
(leaf ace-link :ensure t)
(leaf addressbar
:el-get (addressbar
:type github
:pkgname "lurdan/emacs-addressbar")
:custom
`((addressbar-persistent-history-directory
. ,(expand-file-name my:d:tmp))
(addressbar-ignore-url-regexp
. "\\(://duckduckgo\\.com/\\|google\\.com/search\\)")
(addressbar-search-command-alist
. '("g" . "https://google.com/search?&gws_rd=cr&complete=0&pws=0&tbs=li:1&q="))
(addressbar-display-url-max-length . 60)
))
(leaf shr
:custom
((shr-use-colors . nil)
(shr-use-fonts . nil)
(shr-image-animate . nil)
(shr-width . 72))
)
:bind (("<f2>" . eww)
(:eww-mode-map
("r" . eww-reload)
("o" . eww)
("&" . eww-browse-with-external-browser)
("b" . eww-back-url)
("]" . eww-next-url)
("[" . eww-previous-url)
("g" . eww-top-url)
("+" . my:eww-increase-width)
("-" . my:eww-decrease-width)
("h" . backward-char)
("j" . next-line)
("k" . previous-line)
("l" . forward-char)
("/" . isearch-forward)
("?" . isearch-backward)
("n" . isearch-next)
("N" . isearch-previous)
("f" . ace-link-eww))
)
:custom
`((eww-bookmarks-directory
. ,(expand-file-name "eww" my:d:tmp))
(eww-search-prefix
. "https://www.google.com/search?&gws_rd=cr&complete=0&pws=0&tbs=li:1&q="))
:config
(ace-link-setup-default)
;; :init
;; ;;
;; (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))
;; (add-hook 'eww-mode-hook 'eww-mode-hook--disable-image)
)
-
[ ]
背景色の指定 -
[ ]
幅の強制
日本語入力: ddskk
Daredevil SKK (DDSKK) をメインで使用中.無いと途方に暮れる.
ちなみにGTKが有効になっていると gtk-immodule
なんかと衝突するので
~/.Xresources
で xim を無効にしておくと良い.
例えば以下の様に:
! disable XIM
Emacs*useXIM: false
Emacs 本体側の設定(ddskk)
実際の設定は別ファイルで行なわれるため ここでは設定ファイルの位置変更を変更している.
(defvar skk-user-directory (concat my:d:tmp "skk"))
(unless (file-directory-p skk-user-directory)
(make-directory skk-user-directory))
(unless (locate-library "skk")
(package-install 'ddskk t))
(leaf skk
:commands skk-make-indicator-alist
:bind (("C-x j" . skk-mode)
("C-x C-j" . skk-mode)
("C-\\" . skk-mode))
:init
(setq skk-init-file (concat user-emacs-directory "init-ddskk")
default-input-method "japanese-skk" )
)
DDSKK 本体の設定
基本動作
byte-compile の為の読み込み
(eval-when-compile (require 'skk))
sticky shift: sticky shift を参照のこと. ddskk の 14.2 以降から同梱されるようになった(ありがたい)
(setq skk-sticky-key ";")
変換候補の表示位置
(setq skk-show-candidates-always-pop-to-buffer nil)
候補表示件数を2列に
(setq skk-henkan-number-to-display-candidates 5)
日本語表示しない
(setq skk-japanese-message-and-error nil)
メニューを日本語にしない -> toolbar 非表示だし.
(setq skk-show-japanese-menu nil)
注釈の表示
(setq skk-show-annotation nil)
インジケータの表示のカスタマイズ
(setq skk-latin-mode-string "[_A]")
(setq skk-hiragana-mode-string "[あ]")
(setq skk-katakana-mode-string "[ア]")
(setq skk-jisx0208-latin-mode-string "[A]")
(setq skk-jisx0201-mode-string "[_ア]")
(setq skk-abbrev-mode-string "[aA]")
(setq skk-indicator-use-cursor-color nil)
インジケータを左端に表示
(setq skk-status-indicator 'left)
mode-line が動くのが許せないので, ちょっと修正
(defadvice skk-make-indicator-alist
(after my:set-skk-default-indicator activate)
(dolist (elem
'((abbrev " [aA]" . "--[aA]:")
(latin " [_A]" . "--[_A]:")
(default " [--]" . "--[--]:"))
)
(setq ad-return-value
(append (cons elem nil)
(delq (assoc (car elem) ad-return-value) ad-return-value)))))
;;
;;(setq skk-show-inline t)
カーソルには色をつけない
(setq skk-use-color-cursor nil)
キーバインド
(global-set-key "\C-x\C-j" 'skk-mode)
(global-set-key "\C-xj" 'skk-mode)
(global-set-key "\C-j" 'skk-mode)
(global-set-key "\C-\\" 'skk-mode)
半角カナを入力
(setq skk-use-jisx0201-input-method t)
Enter で改行しない
(setq skk-egg-like-newline t)
"「"を入力したら"」"も自動で挿入
(setq skk-auto-insert-paren t)
句読点変換ルール
(setq skk-kuten-touten-alist
'(
(jp . ("。" . "、"))
(jp-en . ("。" . ", "))
(en-jp . ("." . ","))
(en . (". " . ", "))
))
(setq-default skk-kutouten-type 'en)
全角記号の変換: @ での日付入力は使わない
(setq skk-rom-kana-rule-list
(append skk-rom-kana-rule-list
'(("!" nil "!")
(":" nil ":")
(";" nil ";")
("?" nil "?")
("z " nil " ")
("\\" nil "\\")
("@" nil "@")
)))
送り仮名が厳密に正しい候補を優先
(setq skk-henkan-strict-okuri-precedence t)
辞書の共有
(setq skk-share-private-jisyo t)
変換候補を縦に表示
;; (setq skk-show-inline 'vertical)
(setq skk-show-inline nil)
辞書の設定
追加している辞書の一覧は
といった所. はてなキーワードからの辞書の抽出は znz さんの
を参考に. MatsuCon で公開されている顔文字に関しては 顔文字に ; や が含まれている場合に, 適宜quoteする必要があるので 以下のスクリプトで適当に変換.
#!/usr/bin/env ruby
require 'nkf'
src = ARGV[0]
if ARGV.size < 1
puts "usage: ime2skk.rb ime_dictionary"
exit 0
end
File.open(src, "r") {|f|
f.each do |line|
line_euc = NKF.nkf("-S -e",line)
if line_euc =~ /^([^!]+?)\t(.+?)\t.+$/
entry = $1
content = $2
if content =~/;/
puts entry + " /(concat \"" + content.gsub(';','\\\\073') + "\")/"
elsif content =~/\//
puts entry + " /(concat \"" + content.gsub('/','\\\\057') + "\")/"
else
puts entry + " /" + content + "/"
end
end
end
}
他にも quote する必要あるような気もするけれど, それは気がついた時に.
辞書サーバがそもそも UTF-8 を扱えれば良いのだけれども. 辞書サーバの指定は以下.
;; ddskk <- yaskkserv2 のみ utf-8 で通信するための設定
(defun my:skk-open-server-decoding-utf-8 ()
"辞書サーバと接続する。サーバープロセスを返す。 decoding coding-system が euc ではなく utf8 となる。"
(unless (skk-server-live-p)
(setq skkserv-process (skk-open-server-1))
(when (skk-server-live-p)
(let ((code (cdr (assoc "euc" skk-coding-system-alist))))
(set-process-coding-system skkserv-process
'utf-8 code)))) skkserv-process)
(setq skk-mode-hook
(lambda ()
(advice-add 'skk-open-server :override 'my:skk-open-server-decoding-utf-8)))
(cond
((getenv "SKKSERVER")
(setq skk-server-host (getenv "SKKSERVER")
skk-server-portnum "1178"
skk-large-jisyo nil)
(add-to-list 'skk-search-prog-list
'(skk-server-completion-search) t)
(add-to-list 'skk-search-prog-list
'(skk-comp-by-server-completion) t))
(t
(setq skk-get-jisyo-directory (concat my:d:tmp "skk-jisyo")
skk-large-jisyo (concat skk-get-jisyo-directory "/SKK-JISYO.L"))
(when (file-exists-p "/usr/local/share/skkdic/SKK-JISYO.emoji.utf8")
(setq skk-extra-jisyo-file-list
(list '("/usr/local/share/skkdic/SKK-JISYO.emoji.utf8" . utf-8)))))
)
辞書登録の際に送り仮名を削除
(setq skk-check-okurigana-on-touroku 'auto)
漢字登録のミスをチェックする
(setq skk-check-okurigana-on-touroku t)
個人辞書の文字コード
(setq skk-jisyo-code 'utf-8-unix)
インクリメンタルサーチ
minibuffer 内では強制的に skk off. インクリメンタルサーチは migemo に任せることに.
(add-hook 'skk-mode-hook
(lambda ()
(and (skk-in-minibuffer-p)
(skk-mode-exit))))
(setq skk-isearch-start-mode 'latin)
校正, 辞書等
redpen-paragraph
: redpen による文章校正
(leaf redpen-paragraph
:if (and (executable-find "redpen")
(file-directory-p "~/.config/redpen"))
:ensure t
:bind
(("C-c C-r" . redpen-paragraph))
:hook
((LaTeX-mode-hook
. (lambda ()
(setq redpen-commands
'(
;; for english command
"redpen -r json2 -c ~/.config/redpen/redpen-conf-en.xml -f latex %s 2>/dev/null"
;; for japanese command
"redpen -r json2 -c ~/.config/redpen/redpen-conf-ja.xml -f latex %s 2>/dev/null"
)))
))
:init
(defvar redpen-commands
'(
;; for english command
"redpen -r json2 -c ~/.config/redpen/redpen-conf-en.xml %s 2>/dev/null"
;; for japanese command
"redpen -r json2 -c ~/.config/redpen/redpen-conf-ja.xml %s 2>/dev/null"
))
;;redpen-paragraph-force-reading-whole t
)
ispell
: spell checker
ispell はコマンドとして aspell
を利用する.
(leaf ispell
:if (file-executable-p "aspell")
:custom
(ispell-program-name . "aspell")
:config
(add-to-list 'ispell-skip-region-alist '("[^\000-\377]+"))
)
flyspell
: on-the-fly spell checker [0/1]
flyspell-mode は別途有効化しておいた方が良いのかもしれない
(leaf flyspell
:ensure t
:blackout (flyspell-mode . "F")
:defun
flyspell-emacs-popup-textual
:preface
(defun my:flyspell-popup-choose (orig event poss word)
(if (window-system)
(funcall orig event poss word)
(flyspell-emacs-popup-textual event poss word)))
:advice (:around flyspell-emacs-popup
my:flyspell-popup-choose)
:hook
;; flyspell-prog-mode との switch が欲しい
((LaTeX-mode-hook . flyspell-mode))
)
-
[ ]
flyspell-prog-mode との switch が欲しい
lookup
: 電子辞書の検索
EPWING化した辞書群を検索するために lookup-el
ver. 1.4 系列を利用
(leaf lookup
:if (and (file-exists-p "/etc/emacs/site-start.d/50lookup-el.el")
(file-exists-p "/usr/local/share/dict/lookup-enabled"))
:commands (lookup lookup-region lookup-pattern)
:bind (("C-c w" . lookup-pattern)
("C-c W" . lookup-word))
:custom
(lookup-search-agents
. '((ndeb "/usr/local/share/dict/eijiro" :alias "英辞郎")
(ndeb "/usr/local/share/dict/waeijiro" :alias "和英辞郎")
(ndeb "/usr/local/share/dict/rikagaku5" :alias "理化学辞典 第5版")
(ndeb "/usr/local/share/dict/koujien4" :alias "広辞苑 第4版")
(ndeb "/usr/local/share/dict/wadai5" :alias "研究社 和英大辞典 第5版")
;; (ndeb "/usr/local/share/dict/eidai6" :alias "研究社 英和大辞典 第6版")
;; (ndeb "/usr/local/share/dict/colloc" :alias "研究社 英和活用大辞典 ")
))
)
text-adjust
: 全角文字の撲滅
(leaf text-adjust
:el-get uwabami/text-adjust.el
)
補完: vertico
, marginalia
, consult
最近話題になりだしたので, ちょっと使い始めてみた. 基本機能の拡張なので, 挙動が手に馴染む感じがとても良い.
helm, ivy の無効化
依存する拡張がまだまだ多いので, 一度インストールして邪魔しないようにしておくことに.
(leaf helm :ensure t :defer-config (helm-mode -1))
(leaf ivy :ensure t :defer-config (ivy-mode -1))
無視する拡張子の追加設定
とりあえず, 無視するファイルの拡張子を指定しておく.
(leaf *completion
:init
;; 補完で無視する拡張子の追加.そのうち増える.
(cl-loop for ext in
'(;; TeX
".dvi"
".fdb_latexmk"
".fls"
".ilg"
".jqz"
".nav"
".out"
".snm"
".synctex\\.gz"
".vrb"
;; fortran >= 90
".mod"
;; zsh
".zwc"
;; libtool
".in"
".libs/"
;; fxxkin Apple
".DS_Store"
"._DS_Store"
;; "org-id-locations"
)
do (add-to-list 'completion-ignored-extensions ext))
)
vertico
: 本体
find-fileでHelmみたいにC-lでディレクトリを遡る - emacs
より, C-l
で一つ上の階層へ上がれる様にしたり.
(leaf vertico
:ensure t
:preface
(defun my:disable-selection ()
(when (eq minibuffer-completion-table #'org-tags-completion-function)
(setq-local vertico-map minibuffer-local-completion-map
completion-cycle-threshold nil
completion-styles '(basic))))
;;
(defun my:filename-upto-parent ()
"Move to parent directory like \"cd ..\" in find-file."
(interactive)
(let ((sep (eval-when-compile (regexp-opt '("/" "\\")))))
(save-excursion
(left-char 1)
(when (looking-at-p sep)
(delete-char 1)))
(save-match-data
(when (search-backward-regexp sep nil t)
(right-char 1)
(filter-buffer-substring (point)
(save-excursion (end-of-line) (point))
#'delete)))))
:advice
(:before vertico--setup
my:disable-selection)
:bind
(:vertico-map (("C-l" . my:filename-upto-parent)))
:custom-face
`((vertico-current
. '((t (:inherit hl-line :background unspecified)))))
:custom
`((vertico-count . 9)
(vertico-cycle . t)
(vertico-multiline . '(("↓" 0 1
(face vertico-multiline))
("…" 0 1
(face vertico-multiline))))
)
:config
:hook (after-init-hook . vertico-mode)
)
marginalia
: リッチな注釈(Enable richer annotations)
行揃えが微妙. あと, ファイル名を省略表示できないのかな? ⇒ Better truncation method for file names #70
(leaf marginalia
:ensure t
:bind (("M-A" . marginalia-cycle)
(:minibuffer-local-map
("M-A" . marginalia-cycle)
))
:custom
`((marginalia-annotators
. '(marginalia-annotators-light marginalia-annotators-heavy nil)))
:hook
(after-init-hook . marginalia-mode)
)
consult
: 便利コマンド集
とりあえず recetnf が使えないと途方に暮れるので
consult-recent-file
のカスタマイズのみ.
(leaf consult
:ensure t
:bind (("C-x C-r" . my:consult-recent-file))
:custom
`(;; 増やさないと preview 時に theme がロードされない模様.
;; とりあえず default の 10 倍にしている. 1 MB かな?
(consult-preview-raw-size . 1024000)
(consult-preview-key . ,(kbd "C-M-p"))
(consult-narrow-key . "<")
)
:config
(defun my:consult-recent-file ()
"Find recent using `completing-read' with shorten filename"
(interactive)
(let ((files (mapcar (lambda (f)
(cons (my:shorten-file-path f (- (window-width) 2)) f))
recentf-list)))
(let ((selected
(consult--read (mapcar #'car files)
:prompt "Find recent file: "
:sort nil
:require-match t
:category 'file
:state (consult--file-preview)
:history 'file-name-history)))
(find-file (assoc-default selected files)))))
;; :advice
;; (:override register-preview
;; consult-register-window)
;; :config
;; (setq consult-preview-key (kbd "M-."))
)
consult-ghq
: ghq を consult で.
projectile かなんかを使う方が良さげだが, とりあえず.
(leaf consult-ghq
:el-get uwabami/consult-ghq
:bind (("C-x f" . consult-ghq-open))
:custom
`((consult-ghq-short-list . t))
)
orderless
: 補完候補の選択
イロイロと凝れそうだけど, とりあえずはデフォルトのままで.
(leaf orderless
:ensure t
;; :init (leaf flx :ensure t)
:custom
`((completion-styles . '(orderless))
(orderless-matching-styles
. '(orderless-prefixes
orderless-flex
orderless-regexp
orderless-initialism
orderless-literal))
)
)
翻訳
DeepL 翻訳
ブラウザ呼び出し
(leaf *deepl-translate
:commands my:deepl-translate
:bind (("C-x T" . my:deepl-translate))
:preface
(require 'url-util)
(defun my:deepl-translate (&optional string)
(interactive)
(setq string
(cond ((stringp string) string)
((use-region-p)
(buffer-substring (region-beginning) (region-end)))
(t
(save-excursion
(let (s)
(forward-char 1)
(backward-sentence)
(setq s (point))
(forward-sentence)
(buffer-substring s (point)))))))
(run-at-time 0.1 nil 'deactivate-mark)
(browse-url
(concat
"https://www.deepl.com/translator#en/ja/"
(url-hexify-string string)
)))
)
Google 翻訳
(leaf google-translate
:ensure t
:init
(defvar google-translate-translation-directions-alist '(("en" . "ja") ("ja" . "en")))
(leaf popup :ensure t)
(defun my:google-translate--search-tkk ()
"Search TKK. @see https://github.com/atykhonov/google-translate/issues/52"
(list 430675 2721866130))
:bind
("C-x t" . google-translate-smooth-translate)
:advice (:override google-translate--search-tkk
my:google-translate--search-tkk)
:config
(setq google-translate-translation-directions-alist '(("en" . "ja") ("ja" . "en"))
google-translate-backend-method 'curl)
)
Copy & Paste:
Linux では xclip
を利用
clipboard と PRIMARY の同期には gpaste
を使っている.
(leaf xclip
:if (and (executable-find "xclip")
(eq system-type 'gnu/linux))
:ensure t
:config
(xclip-mode 1))
macOS では pbcopy/pbpaste
を利用.
pbcopy/pbpase
の呼び出し方が変わった? 動かない時がある様な。
(leaf *macOSclipborad
:if (eq system-type 'darwin)
:preface
(defun my:copy-from-osx ()
"Get string via pbpaste"
(shell-command-to-string "pbpaste"))
(defun my:paste-to-osx (text &optional push)
"put `TEXT' via pbcopy with `PUSH' mode"
(let ((process-connection-type nil))
(let ((proc (start-process "pbcopy" "*Messages*" "pbcopy")))
(process-send-string proc text)
(process-send-eof proc))))
:config
(setq interprogram-cut-function 'my:paste-to-osx
interprogram-paste-function 'my:copy-from-osx)
)
ibuffer
: buffer の操作
buffer を眺めるのは ibuffer が好み
(leaf ibuffer
:after all-the-icons-in-terminal
:defun (ibuffer-current-buffer)
:defvar (ibuffer-formats)
:preface
(defun my:ibuffer-find-file ()
"Like `find-file', but default to the directory of the buffer at point."
(interactive)
(let ((default-directory
(let ((buf (ibuffer-current-buffer)))
(if (buffer-live-p buf)
(with-current-buffer buf
default-directory)
default-directory))))
(find-file default-directory)))
;;
:bind (("C-x C-b" . ibuffer-other-window)
("C-x b" . ibuffer-other-window)
("C-x M-b" . ibuffer)
(:ibuffer-mode-map
("C-x C-f" . my:ibuffer-find-file))
)
:config
(define-ibuffer-column icon (:name " ")
(let ((icon
(if (and (buffer-file-name)
(all-the-icons-auto-mode-match?))
(all-the-icons-icon-for-file
(file-name-nondirectory (buffer-file-name)))
(all-the-icons-icon-for-mode major-mode ))))
(if (symbolp icon)
(setq icon
(all-the-icons-faicon
"file-o"
:face 'all-the-icons-dsilver))
icon)))
;;
(setq ibuffer-formats
`((mark modified read-only
" " (icon 2 2 :left :elide)
,(propertize " " 'display `(space :align-to 8))
(name 18 18 :left :elide)
" " (size 9 -1 :right)
" " (mode 16 16 :left :elide) " " filename-and-process)
(mark " " (name 16 -1) " " filename)))
)
wanderulst
: MUA の設定
MUA として Wanderlust を使っている
Emacs 本体側の設定(wanderlust)
Emacs 本体での設定は以下の通り. Wanderlust 自体の設定は別ファイルで行なわれる.
ここでは wl-init-file
を指定することで, 設定ファイルを明示している.
(leaf wl
:if (file-exists-p "/etc/emacs/site-start.d/65wl-beta.el")
:commands (wl wl-other-frame wl-draft wl-user-agent wl-user-agent-compose wl-draft-send wl-draft-kill)
:preface
(defun my:wl-mode-line-buffer-identification (&optional id)
(force-mode-line-update t))
(defconst my:d:wl-cache-directory
(expand-file-name "wanderlust" "~/.cache"))
(unless (file-directory-p
(expand-file-name "local/Trash" my:d:wl-cache-directory))
(make-directory
(expand-file-name "local/Trash" my:d:wl-cache-directory) t))
:advice (:override wl-mode-line-buffer-identification
my:wl-mode-line-buffer-identification)
:custom
`((elmo-msgdb-directory . my:d:wl-cache-directory)
(elmo-maildir-folder-path . my:d:wl-cache-directory)
(elmo-cache-directory . my:d:wl-cache-directory)
(wl-score-files-directory . my:d:wl-cache-directory)
(read-mail-command . #'wl)
(wl-init-file
. ,(expand-file-name "init-wl" user-emacs-directory))
(wl-demo . nil)
)
:init
(define-mail-user-agent
'wl-user-agent
'wl-user-agent-compose
'wl-draft-send
'wl-draft-kill
'mail-send-hook)
)
割と /etc/emacs/site-start.d/65wl-beta.el
と重複している気がするが.
Wanderlust 本体の設定
実際の設定は以下の通り
byte-compile の準備
(eval-and-compile
(leaf el-x
:el-get (el-x
:type github
:pkgname "sigma/el-x"
:build `(("make" ,(format "EMACSBIN=%s" el-get-emacs)))
:load-path "lisp"
)
:require t
)
)
(eval-when-compile
(require 'cp5022x)
(require 'wl)
(require 'mime-def))
依存/追加ライブラリのインストールと読み込み
rail
SEMI や FLIM などの UA の表示に rail を使っている. ちなみに rail を有効にすると, 以下の様に User-Agent が表示される
(leaf rail
:init
(unless (locate-library "rail")
(el-get-bundle uwabami/rail))
(setq rail-emulate-genjis t)
:require t
)
cp5022x を使う
ISO-2022-JP を CP50220 として扱う. Wanderlustと文字コード も参照のこと.
(add-to-list 'mime-charset-coding-system-alist
'(iso-2022-jp . cp50220))
;; fxxkin outlook
(add-to-list 'mime-charset-coding-system-alist
'(gb2312 . gbk))
;;
(setq wl-mime-charset 'iso-2022-jp)
;; (setq wl-mime-charset 'utf-8-uni)
SEMI の追加設定
HTML メールを表示するために eww を使う. mime-setup がロードされる前に記述する必要あり.
(leaf mime-setup
:preface
(leaf w3m-load)
(leaf mime-w3m :require t)
;; (setq mime-view-text/html-previewer 'shr
;; mime-setup-enable-inline-html 'shr)
;; (defvar my:shr-width 72)
;; (defun my:shr-insert-document (&rest them)
;; (let ((shr-width my:shr-width)) (apply them)))
;; (defun my:mime-shr-preview-text/html (&rest args)
;; (advice-add 'shr-insert-document :around 'my:shr-insert-document)
;; (unwind-protect
;; (apply args)
;; (advice-remove 'shr-insert-document 'my:shr-insert-document)))
;; :advice
;; (:around mime-shr-preview-text/html
;; my:mime-shr-preview-text/html)
)
どのアプリケーションで開くか → xdg-open
に丸投げ.
(defvar my-mime-preview-play-current-entity-appname "xdg-open"
"meadow なら fiber, mac なら open, linux なら xdg-open")
(cond
((string-match "apple-darwin" system-configuration)
(setq my-mime-preview-play-current-entity-appname "open")
)
((string-match "linux" system-configuration)
(setq my-mime-preview-play-current-entity-appname "xdg-open")
))
(unless (functionp #'mime-preview-play-current-entity-orig)
(fset #'mime-preview-play-current-entity-orig
(symbol-function #'mime-preview-play-current-entity)))
(defun mime-preview-play-current-entity (&optional ignore-examples mode)
(interactive "P")
(if (and mode (not (equal mode "play")))
(mime-preview-play-current-entity-orig ignore-examples mode)
(let* ((entity (get-text-property (point) 'mime-view-entity))
(name (mime-entity-safe-filename entity))
(filename (expand-file-name (if (and name (not (string= name "")))
name
(make-temp-name "EMI"))
(make-temp-file "EMI" 'directory))))
(mime-write-entity-content entity filename)
(message "External method is starting...")
(let* ((process-name
(concat my-mime-preview-play-current-entity-appname " " filename))
(process
(start-process process-name
mime-echo-buffer-name
my-mime-preview-play-current-entity-appname
filename)))
(set-alist 'mime-mailcap-method-filename-alist process filename)
(set-process-sentinel process 'mime-mailcap-method-sentinel)))))
(setq mime-play-delete-file-immediately nil)
(setq mime-view-mailcap-files '("~/.mailcap"))
~/.mailcap
自体は以下
applications/*; xdg-open %s;
image/*; xdg-open %s;
video/*; xdg-open %s;
MIME の例の保存先の変更
(setq mime-situation-examples-file
(concat my:d:tmp "mime-example"))
text/plain より html を優先 (- -;)
(setq mime-view-type-subtype-score-alist
'(((text . plain) . 1)
((text . html) . 0)
))
音を鳴らすアレやコレの無効化
(setq mime-play-find-every-situations nil
process-connection-type nil)
個人情報の設定
具体的な設定内容は以下のファイルに置いている
(load (concat my:d:password-store "/wl-info.gpg"))
設定している内容は以下の通り
自身のメールアドレスと購読メーリングリストの設定
;; From: の設定
(setq wl-from (concat user-full-name " <" user-mail-address ">"))
;; (system-name) が FQDN を返さない場合、
;; `wl-local-domain' にホスト名を除いたドメイン名を設定
(setq wl-local-domain "example.com")
;; 自分のメールアドレスのリスト
(setq wl-user-mail-address-list
(list (wl-address-header-extract-address wl-from)
;; "e-mail2@example.com"
;; "e-mail3@example.net" ...
))
;; 自分の参加しているメーリングリストのリスト
(setq wl-subscribed-mailing-list
'("wl@lists.airs.net"
"apel-ja@m17n.org"
"emacs-mime-ja@m17n.org"
;; "ml@example.com" ...
))
送受信用サーバの設定
受信(IMAP)
(setq elmo-imap4-default-server "your imap server")
(setq elmo-imap4-default-port '993)
(setq elmo-imap4-default-stream-type 'ssl)
送信(SMTP)
(setq wl-smtp-posting-server "your smtp server")
(setq wl-smtp-posting-user "your account")
(setq wl-smtp-posting-port 587)
(setq wl-smtp-connection-type 'starttls)
(setq wl-smtp-authenticate-type "login")
From に応じて送信サーバをきりかえる.
本来はメール作成時/返信時の template の切り替えなのだれど, 送信時の SMTP の設定を from に合わせてきりかえるようにする. default に二重に指定しているのは, 一度別のアカウントに切り替えた後に再びトグルして戻って来た際に元に戻す(上書き)するため.
(setq wl-template-alist
'(("default"
("From" . wl-from)
(wl-smtp-posting-server . "your smtp server")
(wl-smtp-posting-user . "your account")
(wl-smtp-posting-port . 587)
(wl-smtp-connection-type . 'starttls)
(wl-smtp-authenticate-type . "login")
)
("example1"
("From" . "Your Name <account@example1.com>")
(wl-smtp-posting-server . "smtp.example1.com")
(wl-smtp-posting-user . "your account")
(wl-smtp-posting-port . 587)
(wl-smtp-connection-type . 'starttls)
(wl-smtp-authenticate-type . "login")
)
("example2"
("From" . "Your Name <account@example2.com>")
(wl-smtp-posting-server . "smtp.example2.com")
(wl-smtp-posting-user . "your account")
(wl-smtp-posting-port . 587)
(wl-smtp-connection-type . 'starttls)
(wl-smtp-authenticate-type . "plain")
)
("ssh:smtp"
;; need ssh tunnel
;; ssh -f -N -L 20025:localhost:25 smtp.server.com
("From" . "Your Name <account@example3.com>")
(wl-smtp-posting-server . "localhost")
(wl-smtp-posting-user . "your ssh account")
(wl-smtp-posting-port . 20025)
(wl-smtp-connection-type . 'nil)
(wl-smtp-authenticate-type . 'nil)
)
))
ssh tunnel を自動的にやる事はできないモンだろうか (送信時に open して, 送信後に close する, みたいなの).
ついでに template の切り替えに関して幾つか設定.
;; template 切り替え時に 内容を表示
(setq wl-template-visible-select t)
draft-mode
で C-c C-n
をするとテンプレートを切り替え
(define-key wl-draft-mode-map "\C-c\C-n" 'wl-template-select)
from に応じて wl-from, wl-envelope-from, 送信 smtp サーバを変更する送信時に変更
(add-hook 'wl-draft-send-hook
(lambda ()
(set (make-local-variable 'wl-from)
(std11-fetch-field "From"))))
送信時に自動的に wl-draft-config-alist を適用…しない?
(remove-hook 'wl-draft-send-hook 'wl-draft-config-exec)
基本設定
imap 関連
デフォルトの認証設定 フォルダ名は UTF-7 でエンコードされているので, 表示する際にこれをデコードする
(setq elmo-imap4-use-modified-utf7 t)
非同期チェック
(setq wl-folder-check-async t)
フォルダの位置の default からの変更
~/.cache/wanderlust/
に集約している
local の Mail folder の位置
(setq elmo-maildir-folder-path "~/.cache/wanderlust"
elmo-localdir-folder-path "~/.cache/wanderlust/local")
local フォルダの設定:
.lost+found
は elmo-maildir-folder-path
からの相対パスになっていることに注意
(setq elmo-lost+found-folder ".lost+found")
(setq wl-queue-folder "+queue")
folders の位置の変更
(setq wl-folders-file (concat my:d:password-store "/wl-folders.gpg"))
Drafts, Trash の置き場所
(setq wl-draft-folder "+Drafts")
(setq wl-trash-folder "+Trash")
(setq elmo-lost+found-folder "+lost+found")
(setq wl-temporary-file-directory "~/Downloads/")
アドレス帳
(setq wl-use-petname t)
(setq wl-address-file "~/.mua/Address")
LDAP サーバからアドレスを引くことも可能. 以前は GCALDaemon を使って local に ldap サーバを上げていたのだけれども, Google Contacts の API が変わったらしく GCALDaemon で LDAP サーバは使えなくなったのでコメントアウト.
(setq wl-use-ldap t)
(setq wl-ldap-server "localhost")
(setq wl-ldap-port "389")
(setq wl-ldap-base "dc=math,dc=kyoto-u,dc=ac,dc=jp")
パスワードの保存先
(setq elmo-passwd-alist-file-name (concat my:d:password-store "/wl-passwd.gpg"))
フォルダ編集時に backup を作成しない.
(setq wl-fldmgr-make-backup nil)
FCC, BCC の設定
(setq wl-fcc nil)
;; (setq wl-fcc "%Sent")
fcc を既読にする場合は以下.=wl-fcc= が nil の場合には意味は無い
(setq wl-fcc-force-as-read t)
bcc は常に自身に.
(setq wl-bcc (concat user-mail-address))
起動時に %INBOX
のみをチェック
(setq wl-auto-check-folder-name "%INBOX")
フォルダ選択時の初期設定
imap の namespace を毎度入力するのが面倒なので, これを追加しておく.
(setq wl-default-spec "%")
confirm 関連の設定
スキャン時の問い合わせの無効化. ちなみに confirm を nil にしても 問い合わせが無いだけで threshold は効くので, 明示的に nil に.
(setq elmo-folder-update-confirm nil)
(setq elmo-folder-update-threshold nil)
(setq elmo-message-fetch-confirm nil)
(setq elmo-message-fetch-threshold nil)
(setq wl-prefetch-confirm nil)
(setq wl-prefetch-threshold nil)
終了時に確認しない
(setq wl-interactive-exit nil)
送信時は確認する
(setq wl-interactive-send t)
misc.
大きいメッセージを送信時に分割しない
(setq mime-edit-split-message nil)
スレッドは常に閉じる
(setq wl-thread-insert-opened nil)
3 pain 表示 -> 使わない
(setq wl-stay-folder-window nil)
未読を優先的に読む
(setq wl-summary-move-order 'unread)
改ページ無視
(setq wl-break-pages nil)
icon を使わない → GUI でもメニュー表示してないし, 体感的には遅くなる
(setq wl-highlight-folder-with-icon nil)
dispose, delete の設定
Gmail用に%INBOXでは削除を wl-trash-folder
への移動ではなく, 「delete」に.
(add-to-list 'wl-dispose-folder-alist
'("^%INBOX" . remove))
迷惑メール関連も
(add-to-list 'wl-dispose-folder-alist
'(".*Junk$" . remove))
折り返しの設定
message は折り返す.
(setq wl-message-truncate-lines nil)
draft も折り返す
(setq wl-draft-truncate-lines nil)
mode-line の設定
長いと嫌なのでイロイロ削る
(setq wl-summary-mode-line-format "") ; "%f {%t}(%n/%u/%a)"
(setq wl-message-mode-line-format "") ; "<< %f:%F>> [%m]"
キーバインド関連
C-c C-j
を browse-url に明け渡す
(define-key wl-draft-mode-map "\C-c\C-j" 'browse-url-at-point)
M-u
で unread にする
(define-key wl-summary-mode-map "\M-u" 'wl-summary-mark-as-unread)
i
で sync <- Mew 風
(define-key wl-summary-mode-map "i" 'wl-summary-sync-update)
C-o
は elscreen で使う
(define-key wl-summary-mode-map "\C-o" nil )
M-o
で auto-refile
(Mew 風)
(define-key wl-summary-mode-map "\M-o" 'wl-summary-auto-refile)
flag とフォルダを行き来する関数の追加
"=" でフラグ付きフォルダと 実際にメッセージのあるフォルダを行き来する. Gmail の「スター付き」フォルダでも有効
(require 'elmo nil 'noerror)
(defun my:wl-summary-jump-to-referer-message ()
(interactive)
(when (wl-summary-message-number)
(if (eq (elmo-folder-type-internal wl-summary-buffer-elmo-folder) 'flag)
(progn
(let* ((referer (elmo-flag-folder-referrer
wl-summary-buffer-elmo-folder
(wl-summary-message-number)))
(folder (if (> (length referer) 1)
(completing-read
(format "Jump to (%s): " (car (car referer)))
referer
nil t nil nil (car (car referer)))
(car (car referer)))))
(wl-summary-goto-folder-subr folder 'no-sync nil nil t)
(wl-summary-jump-to-msg (cdr (assoc folder referer)))))
(when (eq (elmo-folder-type wl-summary-last-visited-folder) 'internal)
(wl-summary-goto-last-visited-folder)))))
(define-key wl-summary-mode-map "=" 'my:wl-summary-jump-to-referer-message)
summary-mode の表示のカスタマイズ
自分が差出人である mail は To:某 と表示
(setq wl-summary-showto-folder-regexp ".*")
(setq wl-summary-from-function 'wl-summary-default-from)
サマリ行の表示関連
サマリ行のフォーマット指定
(setq wl-summary-line-format
"%T%P%1@%1>%Y/%M/%D %21(%t%[%19(%c %f%)%]%) %#%~%s"
wl-summary-width (- (window-width) 1))
サマリ表示は切り詰めない
(setq wl-subject-length-limit t)
スレッドの幅の指定
(setq wl-thread-indent-level 2)
(setq wl-thread-have-younger-brother-str "+" ;; "├" ;; "+"
wl-thread-youngest-child-str "+" ;; "└" ;; "+"
wl-thread-vertical-str "|";; "│" ;; "|"
wl-thread-horizontal-str "-";; "─" ;; "-"
wl-thread-space-str " ")
以下の二つの設定を有効にするには
elmo-msgdb-extra-fields
を設定する必要がある.
この変数は振り分け判定にも使用するのでそこで設定している
Gmail 風に, 自分宛のメールに ">" をつけて表示する
元ネタ http://d.hatena.ne.jp/khiker/20080206/wanderlust
(setq wl-user-mail-address-regexp "^uwabami.*\\|^sasakyh.*")
;; 一覧表示での置き換え規則に追加
(defun my:wl-summary-line-for-me ()
(if (catch 'found
(let ((to (elmo-message-entity-field wl-message-entity 'to))
(cc (elmo-message-entity-field wl-message-entity 'cc)))
(when (or (stringp to) cc)
(setq to
(append (if (stringp to) (list to) to)
(when cc
(if (stringp cc) (list cc) cc)))))
(dolist (i to)
(when (wl-address-user-mail-address-p (eword-decode-string i))
(throw 'found t)))))
">"
""))
;; > を summary-line-format に追加
(setq wl-summary-line-format-spec-alist
(append wl-summary-line-format-spec-alist
'((?> (my:wl-summary-line-for-me)))))
添付ファイルがあったら, サマリ行に @ を付ける
(setq wl-summary-line-format-spec-alist
(append wl-summary-line-format-spec-alist
'((?@ (wl-summary-line-attached)))))
クォートされた文字列もデコードする
昔はあれこれ設定してたけど, 今は良いのかな? とりあえず, デコードする長さを default の 1000 から二桁増やしておく.
(setq mime-field-decoding-max-size 100000)
;; (setq mime-header-lexical-analyzer
;; '(
;; eword-analyze-quoted-string
;; eword-analyze-domain-literal
;; eword-analyze-comment
;; eword-analyze-spaces
;; eword-analyze-special
;; eword-analyze-encoded-word
;; eword-analyze-atom))
(with-eval-after-load 'eword-decode
(mime-set-field-decoder
'From nil 'eword-decode-and-unfold-unstructured-field-body)
(mime-set-field-decoder
'CC nil 'eword-decode-and-unfold-unstructured-field-body)
(mime-set-field-decoder
'To nil 'eword-decode-and-unfold-unstructured-field-body))
Subject が変わってもスレッドを切らない
(setq wl-summary-divide-thread-when-subject-changed nil)
Subject での Tab や複数スペースを無視
;; (defadvice std11-unfold-string (after simply activate)
;; (setq ad-return-value
;; (replace-regexp-in-string ad-return-value "[ \t]+" " ")))
重複メッセージを非表示に
フォルダ内の Message-ID が同じメールを非表示にする
(setq wl-folder-process-duplicates-alist
'(
(".*" . hide)
))
sort 順: 返信が来た順
元ネタは Re: wanderlust で GMail 風、新着レス順にソート.
あんまり頑張る気がなかったので el-x
にある dflet
を使っている。
(defun wl-summary-overview-entity-compare-by-reply-date (a b)
"Compare message A and B by latest date of replies including thread."
(dflet ((string-max2 (x y) (cond ((string< x y) y)
('t x)))
(elmo-entity-to-number (x)
(elt (cddr x) 0))
(thread-number-get-date (x)
(timezone-make-date-sortable
(elmo-msgdb-overview-entity-get-date
(elmo-message-entity
wl-summary-buffer-elmo-folder
x))))
(thread-get-family (x)
(cons x (wl-thread-entity-get-descendant
(wl-thread-get-entity x))))
(max-reply-date (x)
(cond ((eq 'nil x)
'nil)
((eq 'nil (cdr x))
(thread-number-get-date (car x)))
('t
(string-max2 (thread-number-get-date (car x))
(max-reply-date (cdr x))))))
)
(string<
(max-reply-date (thread-get-family (elmo-entity-to-number a)))
(max-reply-date (thread-get-family (elmo-entity-to-number b))))))
(add-to-list 'wl-summary-sort-specs 'reply-date)
(setq wl-summary-default-sort-spec 'reply-date)
振り分け設定
$
以外を振り分け対象に
(setq wl-summary-auto-refile-skip-marks '("$"))
振り分け判定に使用するヘッダ
添付の有無の表示にも使うので Content-Type
も登録.
あと Delivered-To
はメールの検索の時に結構重宝している.
(setq elmo-msgdb-extra-fields
'(
"List-Post"
"List-Id"
"List-ID" ;; たまに List-ID で来るメールあるよね?
"Resent-CC"
"Mailing-List"
"X-Mailing-List"
"X-ML-Address"
"X-ML-Name"
"X-ML-To"
"X-Loop"
"Delivered-To"
"Content-Type" ;; 添付の有無の表示の為に追加
"X-Google-Appengine-App-Id" ;; GAEの送信するメールの振り分け用
"To"
"Cc"
"From"
"Subject"
"Reply-To"
"Auto-Submitted" ;; Git commit/Cron notify
))
メッセージ表示
いったん全て非表示に
(setq wl-message-ignored-field-list '("^.*:"))
見たいヘッダだけ表示
(setq wl-message-visible-field-list
'("^Subject:"
"^From:"
"^To:"
"^Cc:"
"^Date:"
"^Message-ID:"
))
表示順の変更
Mew 風…
(setq wl-message-sort-field-list
'("^Subject:"
"^From:"
"^To:"
"^Cc:"
"^Date:"
"^Message-ID:"
))
From, To を省略表示しない
To や From にアドレスが沢山指定されていると省略されるので, これを無効化
(setq wl-message-use-header-narrowing nil)
Wanderlust: Face の設定
デフォルトより細かく指定するために幾つかの face 定義を追加.
(setq wl-highlight-message-header-alist
'(("Subject[ \t]*:"
. wl-highlight-message-subject-header-contents)
("From[ \t]*:"
. wl-highlight-message-from-header-contents)
("Date[ \t]*:"
. wl-highlight-message-date-header-contents)
("\\(.*To\\|Cc\\|Newsgroups\\)[ \t]*:"
. wl-highlight-message-important-header-contents)
("\\(User-Agent\\|X-Mailer\\|X-Newsreader\\)[ \t]*:"
. wl-highlight-message-unimportant-header-contents)
))
;; face の色付け
(defun my:wl-set-face (face spec)
(make-face face)
(cond ((fboundp 'face-spec-set)
(face-spec-set face spec))
(t
(wl-declare-face face spec))))
;;
(my:wl-set-face
'wl-highlight-message-subject-header-contents
'((t (:foreground "#FF5252" :bold t :italic nil :weight bold ))))
(my:wl-set-face
'wl-highlight-message-from-header-contents
'((t (:foreground "#FFD740" :bold t :italic nil :weight bold ))))
(my:wl-set-face
'wl-highlight-message-date-header-contents
'((t (:foreground "#5CF19E" :bold t :italic nil :weight bold ))))
以下, 元々定義されているfaceの設定
;; (my:wl-set-face 'wl-highlight-folder-closed-face
;; '((t (:foreground "#4cff4c" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-folder-few-face
;; '((t (:foreground "#FF4C4C" :bold t :italic nil :weight bold ))))
;; (my:wl-set-face 'wl-highlight-folder-zero-face
;; '((t (:foreground "#f6f3e8" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-message-cited-text-1
;; '((t (:foreground "#7fff7f" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-message-cited-text-2
;; '((t (:foreground "#ffff7f" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-message-cited-text-3
;; '((t (:foreground "#7f7fff" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-message-cited-text-4
;; '((t (:foreground "#7fffff" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-message-cited-text-5
;; '((t (:foreground "#ff7fff" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-message-cited-text-6
;; '((t (:foreground "#ff7f7f" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-message-cited-text-7
;; '((t (:foreground "#4cff4c" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-message-cited-text-8
;; '((t (:foreground "#ffff4c" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-message-cited-text-9
;; '((t (:foreground "#4c4cff" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-message-cited-text-10
;; '((t (:foreground "#4cffff" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-message-cited-text-11
;; '((t (:foreground "#ff4cff" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-message-cited-text-12
;; '((t (:foreground "#ff4c4c" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-message-date-header-contents
;; '((t (:foreground "#4CFF4C" :bold t :italic nil :weight bold ))))
;; (my:wl-set-face 'wl-highlight-message-header-contents
;; '((t (:foreground "#aaaaaa" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-message-headers
;; '((t (:foreground "#4CFFFF" :bold t :italic nil :weight bold ))))
;; (my:wl-set-face 'wl-highlight-message-important-header-contents2
;; '((t (:foreground "#4CFF4C" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-message-signature
;; '((t (:foreground "#aaaaaa" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-message-important-header-contents
;; '((t (:foreground "#FF4CFF" :bold t :italic nil :weight bold ))))
;; (my:wl-set-face 'wl-highlight-message-subject-header-contents
;; '((t (:foreground "#FF4C4C" :bold t :italic nil :weight bold ))))
;; (my:wl-set-face 'wl-highlight-message-unimportant-header-contents
;; '((t (:foreground "#aaaaaa" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-summary-answered-face
;; '((t (:foreground "#4CFF4C" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-summary-refiled-face
;; '((t (:foreground "#7F7FFF" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-summary-thread-top-face
;; '((t (:foreground "#F6F3E8" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-summary-important-flag-face
;; '((t (:foreground "#ffff4c" :bold nil :italic nil :weight normal ))))
;; (my:wl-set-face 'wl-highlight-folder-killed-face
;; '((t (:foreground ,my:h:black :5Dbold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-folder-many-face
;; '((t (:foreground ,my:h:magenta :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-folder-opened-face
;; '((t (:foreground "#4cffff" :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-folder-path-face
;; '((t (:underline t :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-folder-unknown-face
;; '((t (:foreground "#4cffff" :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-folder-unread-face
;; '((t (:foreground ,my:n:blue :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-header-separator-face
;; '((t (:inherit highlight :bold t ))))
;; (my:wl-set-face 'wl-highlight-message-citation-header
;; '((t (:foreground ,my:h:green :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-copied-face
;; '((t (:foreground "#4CFFFF" :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-deleted-face
;; '((t (:foreground ,my:h:black :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-displaying-face
;; '((t (:underline t :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-disposed-face
;; '((t (:foreground "#aaaaaa" :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-flagged-face
;; '((t (:foreground ,my:h:yellow :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-forwarded-face
;; '((t (:foreground ,my:h:blue :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-high-read-face
;; '((t (:foreground ,my:h:green :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-high-unread-face
;; '((t (:foreground ,my:h:orange :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-important-face
;; '((t (:foreground "#ffff4c" :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-killed-face
;; '((t (:foreground ,my:h:black :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-l:read-face
;; '((t (:foreground "#4CFF4C" :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-l:unread-face
;; '((t (:foreground ,my:h:lightb :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-new-face
;; '((t (:foreground "#ff4c4c" :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-normal-face
;; '((t (:foreground "#f6f3e8" :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-prefetch-face
;; '((t (:foreground ,my:n:blue :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-resend-face
;; '((t (:foreground ,my:h:orange :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-target-face
;; '((t (:foreground "#4CFFFF" :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-temp-face
;; '((t (:foreground ,my:n:violet :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-summary-unread-face
;; '((t (:foreground "#ff4c4c" :bold nil :italic nil ))))
;; (my:wl-set-face 'wl-highlight-thread-indent-face
;; '((t (:underline t :bold nil :italic nil ))))
作成/返信設定
自分宛のメールに返信する場合は To:
, Cc:
から自分のアドレスを削除
(setq wl-draft-always-delete-myself t)
"a" (without-argument)では Reply-To:
や From:
などで
指定された唯一人または唯一つの投稿先に返信.
また, X-ML-Name:
と Reply-To:
がついているなら Reply-To:
宛に返信
(setq wl-draft-reply-without-argument-list
'((("X-ML-Name" "Reply-To") . (("Reply-To") nil nil))
("X-ML-Name" . (("To" "Cc") nil nil))
("Followup-To" . (nil nil ("Followup-To")))
("Newsgroups" . (nil nil ("Newsgroups")))
("Reply-To" . (("Reply-To") nil nil))
("Mail-Reply-To" . (("Mail-Reply-To") nil nil))
("From" . (("From") nil nil))))
C-u a
(with-argument)であれば関係する全ての人・投稿先に返信
(setq wl-draft-reply-with-argument-list
'(("Followup-To" . (("From") nil ("Followup-To")))
("Newsgroups" . (("From") nil ("Newsgroups")))
("Mail-Followup-To" . (("Mail-Followup-To") nil ("Newsgroups")))
("From" . (("From") ("To" "Cc") ("Newsgroups")))))
サマリ表示には petname を使うが, 引用には使わない
(setq wl-default-draft-cite-decorate-author nil)
ドラフトの自動保存の無効化
偶に暴発している様な…? elscreen のせいかしら.
(setq wl-auto-save-drafts-interval 300)
メール本文の文字コード
丸囲み数字なんかが入ってしまうと 勝手にエンコーディングが変わってしまって鬱陶しい. どうしたモンだろうかね.
(add-hook 'wl-draft-mode-hook
(lambda ()
(add-to-list 'mime-charset-type-list '(utf-8 8 nil))))
draft mode で orgtbl を有効に
(add-hook 'wl-draft-mode-hook
(lambda ()
(progn
(require 'org-table)
#'turn-on-orgtbl)))
c-sig
署名の選択に c-sig を使用している.
設定は以下の通り. Mew 風に C-c <tab>
で signature を挿入するようにしている
(leaf c-sig
:commands insert-signature-eref
:config
(eval-when-compile (require 'wl))
(setq sig-insert-end t
sig-save-to-sig-name-alist nil
message-signature-file nil)
)
(define-key wl-draft-mode-map "\C-c\t" 'insert-signature-eref)
(add-hook 'wl-draft-mode-hook
(lambda ()
(define-key (current-local-map) "\C-c\C-w"
'insert-signature-eref)))
GPG 署名
以前は mailcrypt を使っていたけれど,
epa があるので主にキーバインドの設定のみ.
draft-mode
の文字コードをあらかじめ指定しておかないと,
送信時に文字コードが変換されるので不正な署名となってしまう.
もっとうまい方法/正攻法がありそうな気がするけれど, 使えてるから, まあ良いかな, とか.
(setq mime-pgp-verify-when-preview nil)
(defun my:epa-wl-decrypt-message ()
(interactive)
(save-window-excursion
(wl-summary-jump-to-current-message)
(wl-message-decrypt-pgp-nonmime)))
(defun my:epa-wl-verify-message ()
(interactive)
(save-selected-window
(wl-summary-jump-to-current-message)
(wl-message-verify-pgp-nonmime)))
(leaf-keys ((:wl-summary-mode-map
("C-c : d" . my:epa-wl-decrypt-message)
("C-c : v" . my:epa-wl-verify-message))
(:wl-draft-mode-map
("C-c : s" . epa-mail-sign)
("C-c : e" . epa-mail-encrypt)))
)
検索
notmuchを使う.
(leaf elmo-search
:config
(elmo-search-register-engine 'notmuch-custom 'local-file
:prog "notmuch-query-custom"
:args '(elmo-search-split-pattern-list)
:charset 'utf-8)
(setq elmo-search-default-engine 'notmuch-custom))
(leaf wl-qs
:config
(setq wl-quicksearch-folder "[]"
)
)
(leaf-keys ((:wl-summary-mode-map
("v" . wl-quicksearch-goto-search-folder-wrapper))
(:wl-folder-mode-map
("v" . wl-quicksearch-goto-search-folder-wrapper)))
)
実際の呼び出しはスレッドを全部取得したいので以下を呼び出している
#!/bin/sh
if [ ! x"$*" = x"" ] ; then
res=$(notmuch search --output=threads "$*")
fi
if [ ! x"$res" = x"" ] ; then
echo $res | xargs notmuch search --sort=oldest-first --output=files
fi
検索時にメールが多すぎると怒られるので. 数字は適当.
(setq elmo-multi-divide-number 2000000
elmo-multi-number 2000000)
Linux Desktop で mailto:
リンクを扱うために
ついでに mailto
のリンクを emacsclient で扱うために,
以下の関数を定義しておく
(defun my:mailto-compose-mail (mailto-url)
"Custom: handling mailto: link"
(if (and (stringp mailto-url)
(string-match "\\`mailto:" mailto-url))
(progn
(eval-and-compile (require 'rfc2368))
(let* ((headers (mapcar (lambda (h) (cons (intern (car h)) (cdr h)))
(rfc2368-parse-mailto-url mailto-url)))
(good-headers (cl-remove-if (lambda (h) (member (car h) '(Body))) headers))
(body (cdr (assoc 'Body headers))))
(wl-draft good-headers nil nil body)))))
Desktop の設定では
#!/bin/sh
# emacs-mailto-handler
mailto=$1
mailto="mailto:${mailto#mailto:}"
mailto=$(printf '%s\n' "$mailto" | sed -e 's/[\"]/\\&/g')
elisp_expr="(my:mailto-compose-mail \"$mailto\")"
emacsclient -a "" -n --eval "$elisp_expr" \
'(set-window-dedicated-p (selected-window) t)'
をメーラとして指定すれば良い.
GNOME は .desktop
ファイルが無いと「お気に入り」登録ができないので
以下のファイルを適当な名前で ~/.local/share/applications/
以下に放り込んでおくと良いだろう
[Desktop Entry]
Name=Emacs Mail Handler
GenericName=Mail User Agent
X-GNOME-FullName=Emacs Mail Handler
Comment=Use emacsclient as MUA, handling mailto link
Keywords=email
Exec=/home/uwabami/bin/emacs-mailto-handler %U
Icon=emacs25
Terminal=false
Type=Application
Categories=GNOME;GTK;Office;Email;
StartupNotify=false
MimeType=application/mbox;message/rfc822;x-scheme-handler/mailto;
メールからの予定の取り込み: mhc
(leaf mhc
:if (file-directory-p (concat (getenv "HOME") "/.config/mhc"))
:ensure t
:disabled t
:commands (mhc-import)
:init
(setq mhc-calendar-day-strings ["日" "月" "火" "水" "木" "金" "土"]
mhc-calendar-header-function 'mhc-calendar-make-header-ja
mhc-calendar-language 'japanese)
)
閉じタグの入力補助: smartparens
(leaf smartparens
:disabled t
:ensure t
:blackout t
:defun (sp-pair)
:hook (after-init-hook . smartparens-global-mode)
:config
(require 'smartparens-config)
(sp-pair "=" "=" :actions '(wrap))
(sp-pair "+" "+" :actions '(wrap))
(sp-pair "<" ">" :actions '(wrap))
(sp-pair "$" "$" :actions '(wrap))
)
カラーコードに色付け: rainbow-mode
#RRGGBB
のカラーコードに勝手に色が付く.CSS の編集中なんかで地味に便利.
(leaf rainbow-mode
:ensure t
:blackout `((rainbow-mode . ,(format " %s" "\x1F308")))
)
対応する括弧を見易く: rainbow-delimiters
対応する括弧を強調表示してくれる RainbowDelimiters: global に有効にするのは他の Major modeとの衝突があるので止めた方が良い, らしい.
(leaf rainbow-delimiters
:ensure t
:blackout t
:hook (prog-mode-hook . rainbow-delimiters-mode)
)
Org-mode
org-mode
が無いと生きていけない体になりました
基本設定: org
目新しい設定はしていない, と思う.
;; org-plus-contrib
(leaf org
:ensure t
:blackout `((org-mode . ,(all-the-icons-icon-for-mode 'org-mode)))
:bind (("C-x n s" . org-narrow-to-subtree)
("C-x n w" . widen)
("C-c a" . org-agenda)
;; ("C-x m" . org-capture)
;; ("C-x M" . org-journal-new-entry)
)
:advice
(:before org-calendar-holiday
(lambda () (require 'japanese-holidays)))
:mode
;; 昔のメモ(howm)も org-mode で開く
(("\\.org\\'" "\\.howm\\'". org-mode))
:preface
;;; timestamp 更新文字列の変更:
;; org-mode では #+DATE: をひっかける用に(#は小文字).
(defun my:org-timestamp-hook ()
"Change `time-stamp-start' in org-mode"
(set (make-local-variable 'time-stamp-start) "#\\+date: ")
(set (make-local-variable 'time-stamp-end) "\$")
)
;; GTD: TODO→...→DONE としたエントリを =Arhive.org= に移動
(defun my:org-archive-done-tasks ()
(interactive)
(org-map-entries 'org-archive-subtree "/DONE" 'file))
:hook
`((org-mode-hook
. ,(lambda ()
(my:org-timestamp-hook)
(leaf org-tempo :require t)))
(org-todo-statistics-hook . my:org-archive-done-tasks)
(org-todo-after-statistics-hook . my:org-archive-done-tasks))
:custom
`(;; Nextcloud に保存する
(org-directory . ,(expand-file-name my:d:org))
;; return でリンクを辿る
(org-return-follows-link . t)
;; 見出しを畳んで表示
(org-startup-folded . t)
;; 折り返し無し
(org-startup-truncated . t)
;; link handler → xdg-open 任せ
(org-file-apps-defaults . '((remote . emacs)
(system . "xdg-open %s")
(t . "xdg-open %s")))
(org-file-apps-defaults-gnu . '((remote . emacs)
(system . "xdg-open %s")
(t . "xdg-open %s")))
(org-file-apps . '((auto-mode . emacs)
("\\.mm\\'" . default)
("\\.x?html?\\'" . "xdg-open %s")
("\\.pdf\\'" . "xdg-open %s")))
;; GTD: 状態の追加
(org-todo-keywords . '((sequence "TODO(t)" "WAIT(w)" "SOMEDAY(s)" "|" "DONE(d)" "CANCEL(c)")
(type "ARTICLE(a)" "|" "DONE(d)")
(type "MEMO(m)" "|" "DONE(d)")))
(org-todo-keyword-faces . '(("TODO" . org-todo)
("WAIT" . org-todo)
("ARTICLE" . (:foreground "#7fbfff" :weight bold))
("MEMO" . (:foreground "#7fbfff" :weight bold))
("SOMEDAY" . (:foreground "#7fff7f" :weight bold))))
;; GTD: タグの追加
(org-tag-alist . '(("OFFICE" . ?o)
("HOME" . ?h)
("MAIL" . ?m)
("WORK" . ?w)
("Debian" . ?d)
("Computer" . ?c)
("Book" . ?b)
("Emacs" . ?e)
("TeX" . ?t)
("Ruby" . ?r)
("IGNORE" . ?i)
("PLANNED" . ?p)
))
;; DONE → Archive.org に移動
(org-archive-location . "Archive.org::")
;; modules → とりあえずクリアしておく
(org-modules . '())
)
:config
;; +打ち消し+ の font-lock の変更 →これはテーマに任せるべき?
(setq org-emphasis-alist
(cons '("+" '(:strike-through t :foreground "#999999"))
(cl-delete "+" org-emphasis-alist :key 'car :test 'equal)))
)
Org-Id
(leaf org-id
:commands
(my:add-custom-id
my:get-custom-id
my:org-custom-id-get
my:delete-all-id-in-file
my:org-id-add-to-headlines-in-file
)
:init
(leaf org-macs :require t)
:custom
`((org-id-locations-file
. ,(expand-file-name "org-id-locations" my:d:tmp))
(org-id-link-to-org-use-id . 'create-if-interactive-and-no-custom-id)
;; (org-id-link-to-org-use-id . create-if-interactive-and-no-custom-id)
)
:config
(defun my:add-custom-id ()
"Add \"CUSTOM_ID\" to the current tree if not assigned yet."
(interactive)
(my:org-custom-id-get nil t))
;;
(defun my:get-custom-id ()
"Return a part of UUID with an \"org\" prefix.
e.g. \"org3ca6ef0c\"."
(let* ((id (org-id-new "")))
(when (org-uuidgen-p id)
(downcase (concat "org" (substring (org-id-new "") 0 8))))))
;;
(defun my:org-custom-id-get (&optional pom create)
"Get the CUSTOM_ID property of the entry at point-or-marker POM.
See https://writequit.org/articles/emacs-org-mode-generate-ids.html"
(interactive)
(org-with-point-at pom
(let ((id (org-entry-get nil "CUSTOM_ID")))
(cond
((and id (stringp id) (string-match "\\S-" id))
id)
(create
(setq id (my:get-custom-id))
(unless id
(error "Invalid ID"))
(org-entry-put pom "CUSTOM_ID" id)
(message "--- CUSTOM_ID assigned: %s" id)
(org-id-add-location id (buffer-file-name (buffer-base-buffer)))
id)))))
;;
(defun my:delete-all-id-in-file ()
(interactive)
(goto-char 1)
(while (not (eq (point) (point-max)))
(org-next-visible-heading 1)
(let ((id (org-entry-get (point) "ID")))
(when id
(message "ID: %s" id)
(org-delete-property "ID"))))
(message "--- done."))
;;
(defun my:org-id-add-to-headlines-in-file ()
"Add CUSTOM_ID properties to all headlines in the current file.
See https://writequit.org/articles/emacs-org-mode-generate-ids.html"
(interactive)
(save-excursion
(widen)
(goto-char (point-min))
(when (re-search-forward "^#\\+options:.*auto-id:t" (point-max) t)
(org-map-entries
(lambda () (my:org-custom-id-get (point) 'create))))))
;;
:hook (before-save-hook
. (lambda ()
(when (and (eq major-mode 'org-mode)
(eq buffer-read-only nil))
(my:org-id-add-to-headlines-in-file))))
)
Babel
(leaf org-babel
:after all-the-icons-in-terminal
:blackout
`((org-src-mode . ,(format " %s" (all-the-icons-octicon "code"))))
:custom
(;; font-lock
(org-src-fontify-natively . t)
;; TAB の挙動
(org-src-tab-acts-natively . t)
;; インデント
(org-edit-src-content-indentation . 0)
;; インデントを残す
(org-src-preserve-indentation . t))
)
Org-capture: メモ取り
キーバインドは以前 changelog memo をやっていた時の癖で C-x m
をメモにしている.
→ capture は org-roam に丸投げすることにした.
(leaf org-capture
:if (file-directory-p my:d:org)
:commands org-capture
;; :pl-setq
;; (my:org:calendar1 my:org:calendar2) ;; 名前がイケてないっ!
:init (leaf doct :ensure t) ;; capture template を上手く書く拡張
:config
(setq org-default-notes-file (expand-file-name "INBOX.org" my:d:org))
(setq org-capture-templates
(doct '(;;
("Org-roam Memo"
:keys "m"
:type plain
:template "* MEMO <%<%Y-%m-%d %H:%M>> %^{title}\n %?"
:target
:prepend nil
:unnarrowed nil
:kill-buffer t
;; :function org-roam-dailies-capture-today
)
("Schedule: 個人スケジュール"
:keys "s"
:type plain
:file (lambda() (expand-file-name "Schedule.org" my:d:org))
:template "* %^{prompt}\n :PROPERTIES:\n :calendar-id: %(format \"%s\" my:org:calendar1)\n :END:\n :org-gcal:\n%?\n%i\n :END:"
:prepend nil
:unnarrowed nil
:kill-buffer t
)
("Univ. Schedule: 大学関連"
:keys "u"
:type plain
:file (lambda() (expand-file-name "Univ.org" my:d:org))
:template "* %^{prompt}\n :PROPERTIES:\n :calendar-id: %(format \"%s\" my:org:calendar2)\n :END:\n :org-gcal:\n%?\n%i\n :END:"
:prepend nil
:unnarrowed nil
:kill-buffer t
)
))
)
)
Org-roam: リンク付きメモ
(leaf org-roam
:if (and (file-directory-p my:d:org)
(and (executable-find "rg")
(executable-find "sqlite3")))
:pl-setq
(my:org:calendar1 my:org:calendar2) ;; 名前がイケてないっ!
:bind
(("C-c n a" . org-roam-alias-add)
("C-c n f" . org-roam-node-find)
("C-c n i" . org-roam-node-insert)
("C-c n o" . org-id-get-create)
("C-c n t" . org-roam-tag-add)
("C-c n l" . org-roam-buffer-toggle)
("C-x m" . org-roam-dailies-capture-today)
)
:ensure t
:init (setq org-roam-v2-ack t)
:custom
`(;; (org-roam-v2-ack . t)
(org-roam-db-location . ,(expand-file-name "org-roam.db" my:d:tmp))
(org-roam-directory . ,(expand-file-name "roam" my:d:org))
(org-roam-mode-section-functions
. (list #'org-roam-backlinks-section
#'org-roam-reflinks-section
;; #'org-roam-unlinked-references-section
))
;; (org-roam-db-update-on-save . t)
(org-roam-dailies-directory . "") ;; relative path→flatten!
(org-roam-dailies-capture-templates
. '(
("m" "memo" entry "* MEMO <%<%Y-%m-%d %H:%M>> %^{title}\n %?"
:target (file+head "%<%Y-%m-%d>.org"
"#+title: %<%Y年%m月%d日(%a)>")
:prepend nil
:kill-buffer t
)
("t" "ToDo" entry "* ToDo <%<%Y-%m-%d %H:%M>> %^{title}\n %?"
:target (file+head "%<%Y-%m-%d>.org"
"#+title: %<%Y年%m月%d日(%a)>")
:prepend nil
:kill-buffer t
)
("s" "Schedule: 個人スケジュール" entry
"* %^{title}\n :PROPERTIES:\n :calendar-id: %(format \"%s\" my:org:calendar1)\n :org-gcal-managed: org\n :END:\n :org-gcal:\n%?\n%i\n :END:"
:target (file ,(expand-file-name "Schedule.org" my:d:org))
:prepend t ;; prepend nil としたいが, 末尾まで行ってくれないので諦める.
:kill-buffer t
)
("u" "Univ: 大学関連 スケジュール" entry
"* %^{title}\n :PROPERTIES:\n :calendar-id: %(format \"%s\" my:org:calendar2)\n :org-gcal-managed: org\n :END:\n :org-gcal:\n%?\n%i\n :END:"
:target (file ,(expand-file-name "Univ.org" my:d:org))
:prepend t ;; prepend nil としたいが, 末尾まで行ってくれないので諦める.
:kill-buffer t
)
))
)
:defer-config
(org-roam-db-autosync-enable)
)
Org-agenda: スケジュール, TODO 表示
GTD 用の設定.後述の org-gcal
と orgmine
で取得したデータも表示している.
ついでに
- 土曜日をの face を追加.
- 祝日, 休日を日曜と同じfaceにする.
なんて事もやっている.元ネタは Org-mode and holidays
(leaf org-agenda
:if (file-directory-p my:d:org)
:defer-config
(defface my:org-agenda-date-saturday
'((t (:foreground "#7FBFFF" :bold t )))
"Agenda 表示中の土曜日用のface")
(defface my:org-agenda-date-today-saturday
'((t (:inherit my:org-agenda-date-saturday :underline t)))
"Agenda 表示中の今日かつ土曜日用のface")
(defface my:org-agenda-date-today-weekend
'((t (:inherit org-agenda-date-weekend :underline t)))
"Agenda 表示中の今日かつ日・祝日用のface")
;; こっからは org-gcal で同期したカレンダーの色
(defface my:org-agenda-calendar-Univ
'((t (:foreground "#7FFF7F")))
"Agenda 表示中, Univ.org の表示 face"
:group 'org-agenda )
(defface my:org-agenda-calendar-Schedule
'((t (:foreground "#7FFFFF")))
"Agenda 表示中, Schedule.org の表示 face"
:group 'org-agenda )
(defface my:org-agenda-calendar-GFD
'((t (:foreground "#FFFF7F")))
"Agenda 表示中, GFD.org の表示 face"
:group 'org-agenda )
(defface my:org-agenda-calendar-DebianJP
'((t (:foreground "#BF7FFF")))
"Agenda 表示中, DebianJP.org の表示 face"
:group 'org-agenda )
(defface my:org-agenda-calendar-twitter
'((t (:foreground "#CCCCCC")))
"Agenda 表示中, Twitter log の表示 face"
:group 'org-agenda )
;; 更新用の関数 - とりあえず動いているので良しとするが,
;; リファクタリングしたい
(defun my:org-agenda-day-face-function (date)
"Compute DATE face for saturday, holidays."
(cl-dolist (file (org-agenda-files nil 'ifmode))
(cond
((member (calendar-day-of-week date) '(0))
(if (org-agenda-todayp date)
(cl-return 'my:org-agenda-date-today-weekend))
(cl-return 'org-agenda-date-weekend))
((member (calendar-day-of-week date) '(6))
(if (org-agenda-todayp date)
(cl-return 'my:org-agenda-date-today-saturday))
(cl-return 'my:org-agenda-date-saturday)))
(let ((face
(cl-dolist (entry (org-agenda-get-day-entries file date))
(let ((category (with-temp-buffer
(insert entry)
(org-get-category (point-min)))))
(when (or (string= "祝日" category)
(string= "休日" category))
(if (org-agenda-todayp date)
(cl-return 'my:org-agenda-date-today-weekend)
(cl-return 'org-agenda-date-weekend)))))))
(when face (cl-return face)))))
(setq org-agenda-day-face-function
'my:org-agenda-day-face-function)
;; font-lock の適用. loop減らせないかなぁ….
(defun my:org-agenda-finalize-font-lock ()
"Custom: apply custom font-lock"
(save-excursion
(goto-char (point-min))
(while (re-search-forward "Univ:" nil t)
(add-text-properties (match-beginning 0) (point-at-eol)
'(face my:org-agenda-calendar-Univ)))
(goto-char (point-min))
(while (re-search-forward "Schedule:" nil t)
(add-text-properties (match-beginning 0) (point-at-eol)
'(face my:org-agenda-calendar-Schedule)))
(goto-char (point-min))
(while (re-search-forward "DebianJP:" nil t)
(add-text-properties (match-beginning 0) (point-at-eol)
'(face my:org-agenda-calendar-DebianJP)))
(goto-char (point-min))
(while (re-search-forward "GFD:" nil t)
(add-text-properties (match-beginning 0) (point-at-eol)
'(face my:org-agenda-calendar-GFD)))
(goto-char (point-min))
(while (re-search-forward "twitter:" nil t)
(add-text-properties (match-beginning 0) (point-at-eol)
'(face my:org-agenda-calendar-twitter)))
(goto-char (point-min))
(while (re-search-forward "祝日:\\|休日:\\|誕生日:" nil t)
(add-text-properties (match-beginning 0) (point-at-eol)
'(face org-agenda-date-weekend)))
))
;;
;;
(add-hook 'org-agenda-finalize-hook
#'my:org-agenda-finalize-font-lock)
;;
(setq org-agenda-span 'day
org-agenda-format-date "%Y/%m/%d (%a)"
org-agenda-start-on-weekday 0
org-agenda-weekend-days '(0)
org-agenda-repeating-timestampo-show-all t
org-agenda-day-face-function 'my:org-agenda-day-face-function
org-agenda-custom-commands
'(
("n" "agenda and all TODO list"
(
(agenda ""
((org-agenda-ndays 1)
(org-agenda-entry-types '(:timestamp :sexp))))
(todo "TODO"
((org-agenda-prefix-format " %i %-22:c")))
(todo "新規|着手|進行中|確認"
((org-agenda-prefix-format " %i %-22:c")))
(todo "WAIT"
((org-agenda-prefix-format " %i %-22:c")))
(todo "SOMEDAY"
((org-agenda-prefix-format " %i %-22:c")))
))
("N" "All memo entry"
(;;
(todo "MEMO")
))
)
)
(dolist (file
'(;; "Archive.org" <-- 🤔
;; Calendar
"Holidays.org"
"Schedule.org"
"GFD.org"
"Univ.org"
"DebianJP.org"
;; INBOX
"INBOX.org"
;; misc
"twitter.org"
;; Project
"redmine_GFD.org"
;; "redmine_FluidSoc.org"
))
(add-to-list 'org-agenda-files (expand-file-name file my:d:org)))
(add-to-list 'org-agenda-files
(locate-user-emacs-file "README.org"))
;; (add-to-list 'org-agenda-files
;; (expand-file-name "Public/web.org" (getenv "HOME")))
;; (add-to-list 'org-agenda-files
;; (expand-file-name "Public/404.org" (getenv "HOME")))
;; org-wiki
;; (dolist (file
;; (directory-files-recursively
;; (expand-file-name "Public/cc-env" (getenv "HOME")) "org$"))
;; (add-to-list 'org-agenda-files file))
;; github repos.
;; (dolist (file
;; (directory-files-recursively
;; (expand-file-name "Public/software" (getenv "HOME")) "org$"))
;; (add-to-list 'org-agenda-files file))
;;
)
Org-roam と Org-agenda
org-roam で db に query 投げて,
org-agenda-files
を更新するように.
元ネタ: Task management with org-roam Vol. 5: Dynamic and fast agenda
(leaf vulpea
:if (and (file-directory-p my:d:org)
(and (executable-find "rg")
(executable-find "sqlite3")))
:after org-agenda
:el-get d12frosted/vulpea
:advice
(:before org-agenda
my:vulpea-agenda-files-update)
:hook
((org-roam-db-autosync-mode . vulpea-db-autosync-enable)
(find-file-hook . vulpea-project-update-tag)
(before-save-hook . vulpea-project-update-tag))
:config
(defun vulpea-project-p ()
"Return non-nil if current buffer has any todo entry.
TODO entries marked as done are ignored, meaning the this
function returns nil if current buffer contains only completed
tasks."
(seq-find ; (3)
(lambda (type)
(eq type 'todo))
(org-element-map ; (2)
(org-element-parse-buffer 'headline) ; (1)
'headline
(lambda (h)
(org-element-property :todo-type h)))))
(defun vulpea-project-update-tag ()
"Update PROJECT tag in the current buffer."
(when (and (not (active-minibuffer-window))
(vulpea-buffer-p))
(save-excursion
(goto-char (point-min))
(let* ((tags (vulpea-buffer-tags-get))
(original-tags tags))
(if (vulpea-project-p)
(setq tags (cons "project" tags))
(setq tags (remove "project" tags)))
;; cleanup duplicates
(setq tags (seq-uniq tags))
;; update tags if changed
(when (or (seq-difference tags original-tags)
(seq-difference original-tags tags))
(apply #'vulpea-buffer-tags-set tags))))))
(defun vulpea-buffer-p ()
"Return non-nil if the currently visited buffer is a note."
(and buffer-file-name
(string-prefix-p
(expand-file-name (file-name-as-directory org-roam-directory))
(file-name-directory buffer-file-name))))
(defun vulpea-project-files ()
"Return a list of note files containing 'project' tag." ;
(seq-uniq
(seq-map
#'car
(org-roam-db-query
[:select [nodes:file]
:from tags
:left-join nodes
:on (= tags:node-id nodes:id)
:where (like tag (quote "%\"project\"%"))]))))
(defun my:vulpea-agenda-files-update (&rest _)
"Update/Add the value of `org-agenda-files'."
(if (vulpea-project-files)
(progn
(dolist (file (vulpea-project-files))
(add-to-list 'org-agenda-files file))
(setq org-agenada-files (delete-dups org-agenda-files)))))
)
OrgとGoogle カレンダーの連携: org-gcal
request token 等の置き場所の変更
実際の情報等は password-store
を使って設定しておく.
ついでに agenda 表示の際の色付けを設定.
(leaf org-gcal
:if (and my:d:password-store
(and (file-directory-p my:d:org)
(executable-find "curl")))
:ensure t
:commands (org-gcal-fetch org-gcal-sync)
:preface
(setq org-gcal-dir (expand-file-name "org-gcal" my:d:tmp))
(unless (file-directory-p org-gcal-dir)
(make-directory org-gcal-dir))
:init
(leaf org-generic-id
:custom
`((org-generic-id-locations-file
. ,(expand-file-name "org-generic-id-locations" my:d:tmp))
)
)
(leaf request
:ensure t
:preface
(setq request-storage-directory (expand-file-name "request" my:d:tmp))
(unless (file-directory-p request-storage-directory)
(make-directory request-storage-directory))
:custom
`((request-storage-directory . ,(expand-file-name "request" my:d:tmp)))
)
(leaf persist
:config
(setq persist--directory-location (expand-file-name "persist" my:d:tmp)))
:custom
`((org-gcal-dir
. ,(expand-file-name "org-gcal" my:d:tmp))
(org-gcal-token-file
. ,(expand-file-name "org-gcal/.org-gcal-token" my:d:tmp))
(org-gcal-down-days . 180) ;; 未来 180 日
(org-gcal-up-days . 30) ;; 過去 30 日
(org-gcal-auto-archive . t)
(org-gcal-notify-p . nil)
(org-gcal-remove-api-cancelled-evetnts . t)
(org-gcal-remove-events-with-cancelled-todo . t)
;;
(alert-log-messages . t)
(alert-default-style .'libnotify))
:pl-setq
(org-gcal-client-id
org-gcal-client-secret
org-gcal-file-alist)
;; :hook (org-capture-after-finalize-hook . org-gcal-fetch)
)
OrgとRedmine の連携: orgmine
素晴しい!! kametoku/orgmine: Emacs minor mode for org-mode with redmine integration
(leaf *orgmine
:if (and my:d:password-store
(file-directory-p my:d:org))
:hook
`(org-mode-hook
. (lambda ()
(if (assoc "om_server" org-keyword-properties)
(orgmine-mode))))
:init
(setq enable-local-variables :safe)
(leaf elmine :ensure t)
;; (add-hook 'org-mode-hook
;; (lambda ()
;; (if (assoc "om_server" org-file-properties) (orgmine-mode))))
(leaf orgmine
:commands (orgmine-mode)
:el-get kametoku/orgmine
:init
;; (defun my:orgmine-default-todo-keyword ()
;; "Custom: use `org-file-properties' for backward compatibility."
;; (or (cdr (assoc-string "om_default_todo" org-file-properties))
;; orgmine-default-todo-keyword
;; (nth 0 org-todo-keywords-1)
;; 1))
;; (defun my:orgmine-setup ()
;; "Custom: use `org-file-properties' for backward compatibility."
;; (let* ((server (cdr (assoc-string "om_server" org-file-properties t)))
;; (config (cdr (assoc-string server orgmine-servers t))))
;; (if config
;; (set (make-local-variable 'orgmine-server) server))
;; (mapc (lambda (elem)
;; (let* ((key (car elem))
;; (symbol (intern (format "orgmine-%s" key)))
;; (value (cdr elem)))
;; (if (memq key orgmine-valid-variables)
;; (progn
;; (set (make-local-variable symbol) value)
;; (if (eq key 'custom-fields)
;; (orgmine-setup-custom-fields value)))
;; (message "orgmine-setup: %s: skipped - invalid name" key))))
;; config))
;; (orgmine-setup-tags)
;; (run-hooks 'orgmine-setup-hook))
;; :advice
;; '((:override orgmine-default-todo-keyword my:orgmine-default-todo-keyword)
;; (:override orgmine-setup my:orgmine-setup))
:pl-setq orgmine-servers
:config
(setq orgmine-note-block-begin "#+begin_src gfm" ;; 要調整
orgmine-note-block-end "#+end_src\n"
orgmine-default-todo-keyword "新規")
)
)
Org-Wiki
(leaf org-wiki
:if (file-directory-p "~/Public/cc-env")
:el-get uwabami/org-wiki
:custom
`((org-wiki-location-alist . '("~/Public/cc-env"))
(org-wiki-location . "~/Public/cc-env")
(org-wiki-publish-relative . t)
(org-wiki-publish-root . "{{site.url}}/cc-env")
(org-wiki-completing-backend . 'completing-read)
(org-wiki-template
. ,(concat "#+TITLE: %n\n"
"#+date: 20\n"
"#+LAYOUT: default\n"
"#+PREMALINK: /cc-env/%n.html\n"
"#+options: auto-id:nil\n"
"#+REF: cc-env/%n\n"
"Related [[wiki:index][Index]] [[~/Public/cc-env/index.org::#orge0707863][Debian]]\n"
"* %n\n"
)))
)
Org-Export
全般設定
latex, beamer,jekyll(後述) のみを有効に.
(leaf ox
:preface
;; 空行の削除
(defun my:remove-org-newlines-at-cjk-text (&optional _mode)
"先頭が '*', '#', '|' でなく、改行の前後が日本の文字の場合は改行を除去"
(interactive)
(goto-char (point-min))
(while (re-search-forward "^\\([^|#*\n].+\\)\\(.\\)\n *\\(.\\)" nil t)
(if (and (> (string-to-char (match-string 2)) #x2000)
(> (string-to-char (match-string 3)) #x2000))
(replace-match "\\1\\2\\3"))
(goto-char (point-at-bol))))
:hook
;; ((org-export-before-processing-hook . my:remove-org-newlines-at-cjk-text))
:custom
((org-export-backends . '(;; remove somve built-in
;; html
jekyll
latex
beamer))
(org-export-with-toc . nil)
(org-export-with-section-numbers . nil))
)
Jekyll, HTML
Web サイトは Jekyll で作成しています. 以前は org file を直接 jekyll で処理していましたが, 最近は org を html に export して, それを処理する様にしています.
exporter は uwabami/ox-jekyll にあります.
(leaf ox-html
:after ox
:init
(leaf ox-jekyll
:if (file-directory-p "~/Public/cc-env")
:el-get uwabami/ox-jekyll)
(leaf s :ensure t)
:custom
((org-html-table-align-individual-fields . nil)
(org-html-table-default-attributes . nil)
(org-html-html5-fancy . t)
(org-html-doctype . "html5")
;; (org-html-container-element . "div")
(org-html-inline-image-rules
. '(("file" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|webp\\|svg\\)\\'")
("http" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|webp\\|svg\\)\\'")
("https" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|webp\\|svg\\)\\'")))
)
:config
;;
(defun my:org-wiki-jekyll-finalized1 (contents backend info)
"Replace some URL"
(when (org-export-derived-backend-p backend 'jekyll)
(require 's)
(s-replace
(format "<a href=\"file://%sREADME.html"
(expand-file-name user-emacs-directory))
"<a href=\"{{baseurl}}/cc-env/Emacs.html"
contents)))
;;
(defun my:org-wiki-jekyll-finalized2 (contents backend info)
"Replace some URL"
(when (org-export-derived-backend-p backend 'jekyll)
(require 's)
(s-replace
(format "<a href=\"file://%s"
(expand-file-name "Public/" (getenv "HOME")))
"<a href=\"{{site.url}}/"
contents)))
;;
(defun my:org-wiki-jekyll-finalized3 (contents backend info)
"Replace some URL"
(when (org-export-derived-backend-p backend 'jekyll)
(replace-regexp-in-string
" id=\"outline-container-org.+\" class=\"outline-.+\""
"" contents)))
;;
(defun my:org-wiki-jekyll-finalized4 (contents backend info)
"Replace some URL"
(when (org-export-derived-backend-p backend 'jekyll)
(replace-regexp-in-string
"<a id=\"org.+?\"></a>"
"" contents)))
;;
(defun my:org-wiki-jekyll-finalized5 (contents backend info)
"Replace some URL"
(when (org-export-derived-backend-p backend 'jekyll)
(replace-regexp-in-string
"<pre class=\"example\" id=\".+?\">"
"<pre class=\"example\">" contents)))
;;
(defun my:org-wiki-jekyll-finalized6 (contents backend info)
"Replace some URL"
(when (org-export-derived-backend-p backend 'jekyll)
(replace-regexp-in-string
"<figure id=\".+?\">"
"<figure>" contents)))
;;
(add-to-list 'org-export-filter-body-functions
'my:org-wiki-jekyll-finalized1)
(add-to-list 'org-export-filter-body-functions
'my:org-wiki-jekyll-finalized2)
(add-to-list 'org-export-filter-body-functions
'my:org-wiki-jekyll-finalized3)
(add-to-list 'org-export-filter-body-functions
'my:org-wiki-jekyll-finalized4)
(add-to-list 'org-export-filter-body-functions
'my:org-wiki-jekyll-finalized5)
(add-to-list 'org-export-filter-body-functions
'my:org-wiki-jekyll-finalized6)
)
LaTeX, Beamer
(leaf ox-latex
:after ox
:preface
:init
(leaf ox-beamer
:custom
`((org-beamer-frame-level . 2)
(org-beamer-frame-default-options . "fragile,squeeze,c")
(org-latex-compiler . "latexmk -pvc")
)
:config
;; for Beamer
(add-to-list 'org-export-options-alist
'(:shortdate "SHORTDATE" nil nil))
(add-to-list 'org-export-options-alist
'(:shorttitle "SHORTTITLE" nil nil))
(add-to-list 'org-export-options-alist
'(:shortauthor "SHORTAUTHOR" nil nil))
(add-to-list 'org-export-options-alist
'(:institute "INSTITUTE" nil nil))
)
:custom
`((org-latex-default-class . "my:uplatex")
(org-latex-pdf-process . '("latexmk -pvc %f"))
(org-latex-hyperref-template
.
"\\hypersetup{
pdfauthor={%a},
pdftitle={%t},
pdfkeywords={%k},
pdfsubject={%d},
pdfcreator={%c},
pdflang={%L},
colorlinks,
}")
(org-latex-classes
. '(("my:uplatex"
"\\documentclass[a4j,uplatex]{jsarticle}
[NO-DEFAULT-PACKAGES] [NO-PACKAGES] [EXTRA]"
("\\section\{%s\}" . "\\section*\{%s\}")
("\\subsection\{%s\}" . "\\subsection*\{%s\}")
("\\subsubsection\{%s\}" . "\\subsubsection*\{%s\}"))
("my:jlreq"
"\\documentclass{jlreq}
[NO-DEFAULT-PACKAGES] [NO-PACKAGES] [EXTRA]"
("\\section\{%s\}" . "\\section*\{%s\}")
("\\subsection\{%s\}" . "\\subsection*\{%s\}")
("\\subsubsection\{%s\}" . "\\subsubsection*\{%s\}"))
("my:beamer"
"\\documentclass[dvipdfmx,presentation]{beamer}
[NO-DEFAULT-PACKAGES] [NO-PACKAGES] [EXTRA]"
("\\section\{%s\}" . "\\section*\{%s\}")
("\\subsection\{%s\}" . "\\subsection*\{%s\}")
("\\subsubsection\{%s\}" . "\\subsubsection*\{%s\}"))))
)
)
Jekyll
Publish
(leaf ox-publish
:if (file-directory-p "~/Public/cc-env")
:after (ox-jekyll org-wiki)
:commands my:org-wiki-publish
:custom
`((org-publish-timestamp-directory
. ,(expand-file-name "org-timestamps/" my:d:tmp)))
:config
(defun my:org-wiki-publish ()
(interactive)
(org-publish (org-wiki-make-org-publish-plist
'org-jekyll-publish-to-html)
t))
)
Org-ref: 文献参照, 引用など
(leaf org-ref
:if (file-directory-p my:d:nextcloud)
:disabled t
:ensure t
:custom
`((org-ref-bibliography-notes . ,(expand-file-name "INBOX.org" my:d:org))
(org-ref-default-bibliography . ,(expand-file-name "references.bib" my:d:nextcloud))
(org-ref-pdf-directory . ,(expand-file-name "Papers" my:d:nextcloud))
)
)
Outline Magic
どんどん増えそう.
(leaf outline
:init
(leaf outline-magic
:ensure t
:bind ((:outline-minor-mode-map
("C-c TAB" . outline-cycle)))
:hook ((LaTeX-mode-hook . my:add-outline-headings)
(LaTeX-mode-hook . outline-minor-mode))
:init
(defun my:add-outline-headings ()
"Custom: Add promotion headings"
(setq outline-promotion-headings '("\\chapter"
"\\section"
"\\subsection"
"\\subsubsection"
"\\paragraph"
"\\subparagraph"
"\\begin{frame}"
)))
)
)
VCS
まあ, ほとんど Git 関連な訳ですが.
git{attributes,config,ignore}-mode, git-commit
(leaf *git
:init
(leaf git-commit :ensure t)
(leaf gitattributes-mode :ensure t)
(leaf gitconfig-mode :ensure t)
(leaf gitignore-mode :ensure t)
)
magit:
magit は Emacs の Git Frontend. 結局の所 CUI でコマンド叩く事も多いけれど, これはこれで重宝している.
(leaf magit
:bind (("C-x g" . magit-status))
:ensure t
:init
(leaf transient
:custom
`((transient-history-file
. ,(expand-file-name "transient-history.el" my:d:tmp))
(transient-levels-file
. ,(expand-file-name "transient-levels.el" my:d:tmp))
(transient-values-file
. ,(expand-file-name "transient-values.el" my:d:tmp))
(transient-force-fixed-pitch . t))
)
:config
(setq magit-completing-read-function 'ido-completing-read
magit-refs-show-commit-count 'all
magit-log-buffer-file-locked t
magit-revision-show-gravatars nil
)
)
Forge
Gitub/Gitlab と Magit の連携
(leaf forge
:disabled t
:after magit
)
Git Gutter+
飽きたら止めるかもしれないけれど.
(leaf git-gutter+
:ensure t
:blackout `((git-gutter+-mode
. ,(format "%s" (all-the-icons-octicon "git-merge"))))
:bind ("C-x G" . global-git-gutter+-mode)
)
関数定義を辿る: dump-jump
, smart-jump
あまり上手く使えていない.
(leaf dumb-jump
:disabled t
:if (executable-find "rg")
:ensure t
:bind (("M-g o" . dumb-jump-go-other-window)
("M-g j" . dumb-jump-go)
("M-g i" . dumb-jump-go-prompt)
("M-g x" . dumb-jump-go-prefer-external)
("M-g z" . dumb-jump-go-prefer-external-other-window))
:custom '((dumb-jump-selector . 'ido)
(dumb-jump-force-searcher . 'rg))
)
(leaf smart-jump
:disabled t
:ensure t
:config
(smart-jump-setup-default-registers)
)
言語毎の補完: company-mode
まだうまく使いこなせていない.
を有効にしてみたが, これで良いのかしら…?
(leaf company
:disabled t
:ensure t
:blackout t
:custom
((company-require-match . 'never)
(company-idle-delay . 0)
(company-selection-wrap-around . t)
(company-tooltip-align-annotations . t)
(company-minimum-prefix-length . 4)
;; disable some noisy default backends
(company-backends . '(company-files
company-capf
(company-dabbrev-code
company-gtags
company-etags
company-keywords))))
:bind
(;; ("<tab>" . company-indent-or-complete-common)
(:company-active-map
("C-n" . company-select-next)
("C-p" . company-select-previous)
("C-s" . company-filter-candidates)
("C-<tab>" . company-complete-common-or-cycle)
("<tab>" . company-indent-or-complete-common)
)
(:company-search-map
("C-p" . company-select-previous)
("C-n" . company-select-next)))
:hook
`((after-init-hook . global-company-mode)
(minibuffer-setup-hook . ,(lambda ()
(company-mode -1)))
)
)
;; (leaf company-statistics
;; :disabled t
;; :ensure t
;; :custom
;; `((company-statistics-size . 2000)
;; (company-statistics-file
;; . ,(expand-file-name "company-statistics-cache.el" my:d:tmp))
;; (company-transformers
;; . (company-sort-by-statistics company-sort-by-backed-importance)))
;; :config
;; (company-statistics-mode)
;; )
;; :init
;; (defun edit-category-table-for-company-dabbrev (&optional table)
;; (define-category ?s "word constituents for company-dabbrev" table)
;; (let ((i 0))
;; (while (< i 128)
;; (if (equal ?w (char-syntax i))
;; (modify-category-entry i ?s table)
;; (modify-category-entry i ?s table t))
;; (setq i (1+ i)))))
;; (edit-category-table-for-company-dabbrev)
;; ;; (add-hook 'TeX-mode-hook 'edit-category-table-for-company-dabbrev) ; 下の追記参照
;; (setq company-dabbrev-char-regexp "\\cs")
SOMEDAY テンプレート補完: yasnippet
[0/1]
(leaf yasnippet
:ensure t
:blackout t
:disabled t
:custom
`((yas-indent-line . 'fixed)
(yas-snippet-dirs . '(,(expand-file-name "snippets" my:d:share))))
:hook (after-init-hook . yas-global-mode)
:bind ((:yas-keymap
("C-<tab>" . nil)
("<tab>" . nil)) ; for company
(:yas-minor-mode-map
("<tab>" . nil)
("C-<tab>" . nil)
("C-c y e" . yas-expand)
("C-c y i" . yas-insert-snippet)
("C-c y n" . yas-new-snippet)
("C-c y v" . yas-visit-snippet-file)
("C-c y l" . yas-describe-tables)
("C-c y g" . yas-reload-all)))
:init
(leaf yasnippet-snippets :ensure t)
(leaf yatemplate :ensure t)
)
-
[ ]
意図しない所で発火してテンプレートが挿入されてしまうので保留中
SOMEDAY flymake
: on-the-fly check [0/1]
on-the-fly syntax checker.
同様の拡張には flycheck
があるけれど,
flycheck
はいろいろやりすぎてて私には合わない.
(leaf flymake
:ensure t
)
-
[ ]
設定調整が必要
LSP: lsp-mode
(leaf lsp-mode
:disabled t
:if (executable-find "fortls")
:ensure t
:custom
`((lsp-print-io . nil)
(lsp-trace . nil)
(lsp-print-performance . nil)
(lsp-auto-guess-root . t)
(lsp-document-sync-method . 'incremental)
(lsp-response-timeout . 5)
(lsp-prefer-flymake .'flymake)
(lsp-session-file .,(expand-file-name "lsp-session-v1" my:d:tmp))
)
:init
(leaf lsp-ui
:ensure t
:custom
((lsp-ui-doc-enable . t)
(lsp-ui-doc-header . t)
(lsp-ui-doc-include-signature . t)
(lsp-ui-doc-position . 'at-point)
(lsp-ui-doc-max-width . 150)
(lsp-ui-doc-max-height . 30)
(lsp-ui-doc-use-childframe . nil)
(lsp-ui-doc-use-webkit . nil)
(lsp-ui-flycheck-enable . nil)
(lsp-ui-peek-enable . t)
(lsp-ui-peek-peek-height . 20)
(lsp-ui-peek-list-width . 50)
(lsp-ui-peek-fontify . 'on-demand) ;; never, on-demand, or always
)
)
:hook
((lsp-mode-hook . lsp-ui-mode)
(f90-mode-hook . lsp))
)
TeX: AUCTeX
やっている事は
- japanese-latex-mode において, 幾つかのコマンドが追加/上書きされているが, あまり使うことの無いコマンドが表示されるのが嫌なのでそれらを削除.
- コンパイルにはLatexmkを使う
と言った所.
…ただ, Beamerのクラスなんかだと勝手にdefault コマンドが LaTeX に変更されたりするので挙動がイマイチ良くわからん.
async で latexmk -pvc
を走らせておいた方が気持が良い, 気がしている….
(leaf auctex
:if (and (executable-find "uplatex")
(executable-find "latexmk"))
:load-path "/usr/share/emacs/site-lisp/auctex"
:init
(unless (file-directory-p (expand-file-name "auctex/auto" my:d:tmp))
(progn
(make-directory (expand-file-name "auctex/auto" my:d:tmp) t)
(make-directory (expand-file-name "auctex/style" my:d:tmp) t)))
(leaf reftex
:custom ((reftex-plug-into-AUCTeX . t)
(reftex-cite-prompt-optional-args . t)
(reftex-toc-split-windows-horizontally . t)
)
)
(leaf auctex-latexmk
:el-get tom-tan/auctex-latexmk
:custom
`((auctex-latexmk-inherit-TeX-PDF-mode . t))
:config
(setq TeX-command-output-list '(("LaTeXMk" ("pdf")))
TeX-command-default "LaTexMk"
japanese-LaTeX-command-default "LaTeX")
)
(load "auctex" t t)
(load "preview-latex" t t)
:hook
(LaTeX-mode-hook . (lambda ()
(turn-on-reftex)
(auctex-latexmk-setup)
(setq-default TeX-command-default "LaTexMk"
japanese-LaTeX-command-default "LaTeX")
(TeX-PDF-mode)
(TeX-source-correlate-mode)
(LaTeX-math-mode)
(outline-minor-mode)
))
:custom
`((TeX-auto-local
. ,(expand-file-name "auctex/auto" my:d:tmp))
(TeX-style-local
. ,(expand-file-name "auctex/style" my:d:tmp))
(TeX-default-mode . 'japanese-latex-mode) ;; 🤔
(japanese-TeX-engine-default . 'uptex)
(japanese-LaTeX-default-style . "jlreq") ;; jsarticle? bxjsarticle?
(TeX-engine . 'uptex)
(TeX-PDF-from-DVI . "Dvipdfmx")
(TeX-view-program-selection . '((output-dvi "xdvi")
(output-pdf "Evince")
(output-html "xdg-open")))
(LaTeX-figure-label . "fig:")
(LaTeX-table-label . "tab:")
(LaTeX-section-label . "sec:")
(TeX-command-default . "LaTexMk")
(TeX-parse-self . t)
(TeX-auto-save . t)
(TeX-auto-untabify . t)
(TeX-source-correlate-mode . t)
(TeX-source-correlate-start-server . t)
(TeX-source-correlate-method . 'synctex)
(font-latex-fontify-script . nil)
(font-latex-script-display . nil)
(font-latex-fontify-sectioning . 1.0)
)
)
Autoconf
いれてみたけれど, はてさて.
(leaf sh-autoconf
:el-get (sh-autoconf
:type http
:url "https://download.tuxfamily.org/user42/sh-autoconf.el")
:mode (("/configure\\.\\(ac\\|in\\)\\'" . sh-mode)
("/ac\\(include\\|local\\)\\.m4\\'" . sh-mode))
)
Fortran
(leaf f90
:mode ("\\.\\(f|F\\)\\(90|95|03|08\\)$" . f90-mode)
:init
(leaf f90-indent
:custom
((f90-do-indent . 3) ;; 2? 4?
(f90-if-indent . 3) ;; 2? 4?
(f90-type-indent . 3) ;; 2? 4?
(f90-program-indent . 3) ;; 2? 4?
(f90-continuation-indent . 3) ;; 2? 4?
(f90-directive-comment-re . "!omp\\$" )
(f90-indented-comment-re . "!" )
(f90-break-delimiters . "[-+\\*/><=,% \t]")
(f90-break-before-delimiters . t)
(f90-beginning-ampersand . nil)
(f90-smart-end . 'blink)
(f90-auto-keyword-case . nil)
(f90-leave-line-no . nil)
(f90-comment-region . "!! ")
(f90-indent-comment . "! "))
)
)
Markdown
markdown自体はあまり好きじゃないんだけれど, 必要に迫られて書く事が増えてきたので設定しておく.
(leaf markdown-mode
:if (executable-find "pandoc")
:mode ("\\.\\(md\\|markdown\\|mkd\\)\\'" . gfm-mode)
:preface
(defun my:disable-electric-indent-local-mode ()
(electric-indent-local-mode -1))
:hook
`((markdown-mode-hook . my:disable-electric-indent-local-mode)
(gfm-mode-hook . my:disable-electric-indent-local-mode))
:custom
`((markdown-command
. "pandoc --from markdown_github -t html5 --mathjax --highlight-style pygments"))
)
SCSS
ちょいちょい弄る機会が増えてきたので導入.
(leaf scss-mode
:if (executable-find "sass")
:ensure t
:mode "\\.scss\\'"
:custom
`((scss-sass-command . ,(executable-find "sass")))
)
PlantUML
(leaf plantuml-mode
:if (executable-find "plantuml")
:ensure t
:custom
`((plantuml-executable-path . ,(executable-find "plantuml"))
(plantuml-default-exec-mode . 'executable))
:init
;; (add-to-list
;; 'org-src-lang-modes '("plantuml" . plantuml))
)
Re:VIEW
(leaf review-mode
:ensure t
:custom
`((review-mode-use-skk-mode . t)
(reivew-use-em . t)
)
)
その他のモード設定
読み込むだけの mode の設定. 設定が増えたら別途まとめる。
(leaf *misc-mode
:init
(leaf flycheck
:disabled t
:ensure t
:config
(flycheck-define-checker
textlint
"A linter for prose."
:command ("textlint" "--format" "unix"
;; "--rule" "no-mix-dearu-desumasu" "--rule" "max-ten" "--rule" "spellcheck-tech-word"
source-inplace)
:error-patterns
((warning line-start (file-name) ":" line ":" column ": "
(id (one-or-more (not (any " "))))
(message (one-or-more not-newline)
(zero-or-more "\n" (any " ") (one-or-more not-newline)))
line-end))
:modes (text-mode markdown-mode gfm-mode wl-draft-mode))
(add-to-list 'flycheck-checkers 'textlint)
)
(leaf debian-el
:custom
`((debian-bug-download-directory . "~/Downloads"))
)
(leaf rd-mode
:mode "\\.rd$"
:hook
(rd-mode-hook . rd-show-other-block-all))
(leaf yaml-mode
:ensure t
:mode "\\(\.yml\\|\.yaml\\)"
)
(leaf generic-x)
(leaf textile-mode :ensure t)
(leaf lua-mode :ensure t)
(leaf debian-el)
(leaf dpkg-dev-el)
(leaf sh-mode
:custom ((system-uses-terminfo . nil))
)
(leaf apt-sources-list :ensure t
:custom
((apt-sources-list-suites
. '("stable" "stable-backports"
"testing" "testing-backports"
"unstable" "experimental"
"jessie" "jessie-backports"
"stretch" "stretch-backports"
"buster" "buster-backports"
"bullseye"
"sid")))
)
(leaf woman
;; :custom-face
;; ((woman-bold . '((t (:inherit font-lock-type-face :bold t))))
;; (woman-italic . '((t (:inherit font-lock-keyword-face :underline t)))))
)
(leaf info-colors
:ensure t
:hook
(Info-selection #'info-colors-fontify-node))
)
SSH config mode
(leaf ssh-config-mode
:ensure t
:mode ((("/\\.ssh/config\\'" "/sshd?_config\\'") . ssh-config-mode)
("/known_hosts\\'" . ssh-known-hosts-mode)
("/authorized_keys?\\'" . ssh-authorized-keys-mode))
:hook (ssh-config-mode . turn-on-font-lock)
)
SOMEDAY 日記: tDiary
[0/1]
(leaf tdiary-mode
:if (and my:d:password-store
(file-directory-p (concat (getenv "HOME") "/Nextcloud/tdiary")))
:commands (tdiary-mode tdiary-replace tdiary-append)
:el-get uwabami/tdiary-mode
:defvar tdiary-passwd-file
:pl-setq
(tdiary-csrf-key tdiary-passwd-file)
;; :init
;; (setq tdiary-text-save-p t)
:config
(setq tdiary-text-directory (concat (getenv "HOME") "/Nextcloud/tdiary/")
tdiary-diary-list '(("log" "https://uwabami.junkhub.org/log/"))
tdiary-style-mode 'org-mode
tdiary-text-suffix ".org"
tdiary-http-timeout 100
)
(tdiary-passwd-file-load)
;; (with-eval-after-load 'tdiary-mode
;; (setq tdiary-text-save-p t))
)
-
[ ]
org2blog で tDiary を更新できないか妄想している
テーマ, フォント, モードライン, などなど
SOMEDAY フォント [0/1]
試行錯誤中. とはいえ, GUIで使う事は滅多に無いのでなかなか弄る機会が無い.
;;;###autoload
(defun my:load-window-config ()
"load window-system specific settings"
(interactive)
(progn
(set-face-attribute 'default nil
:family "FSMRMP"
:height 220)
(set-face-attribute 'fixed-pitch nil
:family "FSMRMP"
:height 220)
(set-face-attribute 'variable-pitch nil
:family "FSMRMP"
:height 220)
;; Japanese
(set-fontset-font nil
'japanese-jisx0213.2004-1
(font-spec :family "AGVRMP" :height 220))
(set-fontset-font nil
'japanese-jisx0213-2
(font-spec :family "AGVRMP" :height 220))
(set-fontset-font nil
'katakana-jisx0201
(font-spec :family "AGVRMP" :height 220))
;; Latin with pronounciation annotations
(set-fontset-font nil
'(#x0080 . #x024F)
(font-spec :family "AGVRMP" :height 220))
;; Math symbols
(set-fontset-font nil
'(#x2200 . #x22FF)
(font-spec :family "AGVRMP" :height 220))
;; Greek
(set-fontset-font nil
'(#x0370 . #x03FF)
(font-spec :family "AGVRMP" :height 220))
;; Some Icons
(set-fontset-font nil
'(#xE0A0 . #xEEE0)
(font-spec :family "AGVRMP" :height 220))
))
;;;###autoload
(defun my:load-side-window-config ()
"load window-system specific settings"
(interactive)
(progn
(set-face-attribute 'default nil
:family "AGVRMP"
:height 180)
(set-face-attribute 'fixed-pitch nil
:family "AGVRMP"
:height 180)
(set-face-attribute 'variable-pitch nil
:family "AGVRMP"
:height 180)
;; Japanese
(set-fontset-font nil
'japanese-jisx0213.2004-1
(font-spec :family "AGVRMP" :height 180))
(set-fontset-font nil
'japanese-jisx0213-2
(font-spec :family "AGVRMP" :height 180))
(set-fontset-font nil
'katakana-jisx0201
(font-spec :family "AGVRMP" :height 180))
;; Latin with pronounciation annotations
(set-fontset-font nil
'(#x0080 . #x024F)
(font-spec :family "AGVRMP" :height 180))
;; Math symbols
(set-fontset-font nil
'(#x2200 . #x22FF)
(font-spec :family "AGVRMP" :height 180))
;; Greek
(set-fontset-font nil
'(#x0370 . #x03FF)
(font-spec :family "AGVRMP" :height 180))
;; Some Icons
(set-fontset-font nil
'(#xE0A0 . #xEEE0)
(font-spec :family "AGVRMP" :height 180))
))
(leaf *gui
:if window-system
:config
(set-frame-parameter nil 'alpha 90)
(setq use-default-font-for-symbols nil)
(scroll-bar-mode -1)
;; (my:load-window-config)
)
-
[ ]
FSMRMP のギリシャ文字が全角にならない. 要調整
幅の確認: Greek, Math, 絵文字は全角, 他は半角で 2:1 になっているかの確認用 |abcdefghijkl| |ABCDEFGHIJKL| |'";:-+=/\~`?| |∞≤≥∏∑∫| |×±≒≡⊆⊇| ← GUI だと一部半角になる |αβγδεζ| ← GUI だと半角になる |ηθικλμ| ← GUI だと半角になる |ΑΒΓΔΕΖ| ← GUI だと半角になる |ΗΘΙΚΛΜ| ← GUI だと半角になる |日本語の美観| |あいうえおか| |アイウエオカ| |アイウエオカキクケコサシ| | hoge | hogeghoe | age | |----------------------+----------+------------------| | 今日もいい天気ですね | お、 | 等幅になった👍 🍺| |----------------------+----------+------------------|
modeline: powerline
(leaf powerline
:ensure t
:init
(defun my:powerline-ddskk ()
"skkが読み込まれていなくても状態を表示"
(cond
((not (boundp 'skk-modeline-input-mode))
(setq skk-modeline-input-mode "--[--]:"))
(t skk-modeline-input-mode)))
;;
(defun my:skk-setup-modeline ()
"skk-setup-modeline による modeline の更新を無効化"
(setq skk-indicator-alist (skk-make-indicator-alist))
(force-mode-line-update t))
;;
(defun my:major-mode-icon (mode)
"Update file icon in mode-line, just display major-mode icon. not filename."
(let* ((icon (all-the-icons-icon-for-mode mode)))
(if (symbolp icon)
(all-the-icons-faicon "file-code-o"
:face 'all-the-icons-dsilver
:height 1.0)
icon)))
:advice (:override skk-setup-modeline my:skk-setup-modeline)
:custom
`((powerline-buffer-size-suffix . nil)
(powerline-display-hud . nil)
(powerline-display-buffer-size . nil)
(powerline-text-scale-factor . 1)
)
:config
(defun my:powerline-theme ()
"Setup the default mode-line."
(interactive)
(my:powerline-ddskk)
(setq-default
mode-line-format
'("%e"
(:eval
(let* ((active (powerline-selected-window-active))
(mode-line-buffer-id (if active 'mode-line-buffer-id 'mode-line-buffer-id-inactive))
(mode-line (if active 'mode-line 'mode-line-inactive))
(face0 (if active 'powerline-active0 'powerline-inactive0))
(face1 (if active 'powerline-active1 'powerline-inactive1))
(face2 (if active 'powerline-active2 'powerline-inactive2))
(lhs (list (powerline-raw (substring skk-modeline-input-mode 2 -1) mode-line 'l)
(powerline-raw "%*" mode-line 'l)
(powerline-raw mode-line-mule-info mode-line 'l)
(powerline-raw (my:major-mode-icon major-mode) mode-line 'l)
(powerline-buffer-id mode-line-buffer-id 'l)
(powerline-raw " ")
))
(rhs (list (powerline-raw global-mode-string face1 'r)
(powerline-vc face1 'r)
(powerline-raw " ")
(powerline-raw "%6p" mode-line 'r)
)))
(concat (powerline-render lhs)
(powerline-fill face2 (powerline-width rhs))
(powerline-render rhs))))))
)
(my:powerline-theme)
)
theme: modus-theme
最近乗り換えた. じたばたしているのは背景透過と Wanderlust の face の追加, かな? あとはデフォルトの font-lock を(好みに合わせて)入れ替えたり.
(leaf modus-themes
:ensure t
:bind ("<f5>" . modus-themes-toggle)
:init
(modus-themes-load-themes)
:config
(modus-themes-load-vivendi)
:preface
(defun my:set-background (&optional frame)
"Unsets the background color for transparency"
(or frame
(setq frame (selected-frame)))
(if (display-graphic-p frame)
(progn
(set-frame-parameter nil 'alpha '(80 50))
(add-to-list 'default-frame-alist '(alpha 80 50)))
(set-face-background 'default "unspecified-bg" frame)))
;; (my:modus-themes-custom-faces)
(defun my:modus-themes-custom-faces ()
(modus-themes-with-colors
(custom-set-faces
;;
;; `(modus-themes-hl-line ((,class ,@(modus-themes--hl-line
;; bg-hl-line bg-hl-line-intense
;; bg-hl-line-intense-accent blue-nuanced-bg
;; bg-region blue-intense-bg
;; fg-alt cyan-intense)
;; :extend t)))
;; `(hl-line ((,class :background "#556b2f")))
;;
;; preprocessor → builtin
`(font-lock-builtin-face ((,class ,@(modus-themes--syntax-extra
blue-alt-other blue-alt-other-faint
blue-alt blue-alt-faint))))
;; preprocessor:: red
`(font-lock-preprocessor-face ((,class :inherit modus-themes-bold
,@(modus-themes--syntax-extra
red-alt red-alt-faint
red-intense red-faint))))
;; constant → function
`(font-lock-function-name-face ((,class ,@(modus-themes--syntax-extra
blue-alt-other blue-alt-other-faint
magenta-alt-other magenta-alt-other-faint))))
;; constant :: custom
`(font-lock-constant-face ((,class ,@(modus-themes--syntax-extra
orange-intense orange-intense
orange-intense orange-intense))))
;; keyword → string
`(font-lock-string-face ((,class :inherit modus-themes-bold
,@(modus-themes--syntax-extra
magenta-alt-other magenta-alt-other-faint
cyan cyan-faint))))
;; keyword :: custom
`(font-lock-keyword-face ((,class :inherit modus-themes-bold
,@(modus-themes--syntax-extra
red-alt-other red-alt-other-faint
red-alt-other red-alt-other-faint))))
;; type → negation-char
`(font-lock-negation-char-face ((,class :inherit modus-themes-bold
,@(modus-themes--syntax-foreground
cyan-alt-other cyan-alt-faint))))
;; type :: custom
`(font-lock-type-face ((,class :inherit modus-themes-bold
,@(modus-themes--syntax-foreground
yellow-intense yellow-faint))))
`(font-lock-regexp-grouping-backslash ((,class :inherit bold
,@(modus-themes--syntax-string
fg-escape-char-backslash fg-escape-char-backslash
fg-escape-char-backslash fg-escape-char-backslash
))))
`(font-lock-regexp-grouping-construct ((,class :inherit bold
,@(modus-themes--syntax-string
fg-escape-char-construct fg-escape-char-construct
fg-escape-char-construct fg-escape-char-construct
))))
;; カスタマイズ済みなので上書き
`(org-agenda-date-weekend
((,class :inherit 'default :foreground "#ff7f7f" :bold t)))
`(org-agenda-date
((,class :inherit 'default :foreground "#ffffff" :bold t )))
`(org-agenda-date-today
((,class :inherit 'default :foreground "#ffffff" :bold t :underline)))
;; 不要
`(org-block-begin-line ((,class :background nil)))
`(org-block-end-line ((,class :background nil)))
;; shell の lscolors に揃える.
`(dired-directory ((,class :foreground "#7f7fff" :bold t)))
;;
;; wanderlust
`(wl-highlight-folder-closed-face ((,class ,@(modus-themes--syntax-string green-alt-other green-alt-other green-alt-other green-alt-other ))))
`(wl-highlight-folder-few-face ((,class ,@(modus-themes--syntax-string red-alt-other red-alt-other red-alt-other red-alt-other ))))
`(wl-highlight-folder-killed-face ((,class ,@(modus-themes--syntax-string fg-alt fg-alt fg-alt fg-alt ))))
`(wl-highlight-folder-many-face ((,class ,@(modus-themes--syntax-string magenta magenta magenta magenta ))))
`(wl-highlight-folder-opened-face ((,class ,@(modus-themes--syntax-string cyan-alt-other cyan-alt-other cyan-alt-other cyan-alt-other ))))
`(wl-highlight-folder-path-face ((,class :underline t :bold t)))
`(wl-highlight-folder-unknown-face ((,class ,@(modus-themes--syntax-string cyan-alt cyan-alt cyan-alt cyan-alt ))))
`(wl-highlight-folder-unread-face ((,class ,@(modus-themes--syntax-string blue-alt blue-alt blue-alt blue-alt ))))
`(wl-highlight-folder-zero-face ((,class ,@(modus-themes--syntax-string fg-main fg-main fg-main fg-main))))
`(wl-highlight-message-citation-header ((,class ,@(modus-themes--syntax-string green-active green-active green-active green-active))))
`(wl-highlight-message-cited-text-1 ((,class ,@(modus-themes--syntax-string green-intense green-intense green-intense green-intense))))
`(wl-highlight-message-cited-text-2 ((,class ,@(modus-themes--syntax-string yellow-intense yellow-intense yellow-intense yellow-intense))))
`(wl-highlight-message-cited-text-3 ((,class ,@(modus-themes--syntax-string blue-intense blue-intense blue-intense blue-intense))))
`(wl-highlight-message-cited-text-4 ((,class ,@(modus-themes--syntax-string cyan-intense cyan-intense cyan-intense cyan-intense))))
`(wl-highlight-message-cited-text-5 ((,class ,@(modus-themes--syntax-string purple-intense purple-intense purple-intense purple-intense))))
`(wl-highlight-message-cited-text-6 ((,class ,@(modus-themes--syntax-string red-intense red-intense red-intense red-intense))))
`(wl-highlight-message-cited-text-7 ((,class ,@(modus-themes--syntax-string green-intense green-intense green-intense green-intense))))
`(wl-highlight-message-cited-text-8 ((,class ,@(modus-themes--syntax-string yellow-intense yellow-intense yellow-intense yellow-intense))))
`(wl-highlight-message-cited-text-9 ((,class ,@(modus-themes--syntax-string blue-intense blue-intense blue-intense blue-intense))))
`(wl-highlight-message-cited-text-10 ((,class ,@(modus-themes--syntax-string cyan-intense cyan-intense cyan-intense cyan-intense))))
`(wl-highlight-message-header-contents ((,class ,@(modus-themes--syntax-string purple-intense purple-intense purple-intense purple-intense))))
`(wl-highlight-message-headers ((,class ,@(modus-themes--syntax-string cyan-intense cyan-intense cyan-intense cyan-intense))))
`(wl-highlight-message-important-header-contents ((,class ,@(modus-themes--syntax-string magenta-intense magenta-intense magenta-intense magenta-intense))))
`(wl-highlight-message-important-header-contents2 ((,class ,@(modus-themes--syntax-string magenta-intense magenta-intense magenta-intense magenta-intense))))
`(wl-highlight-message-signature ((,class ,@(modus-themes--syntax-string fg-dim fg-dim fg-dim fg-dim))))
`(wl-highlight-message-unimportant-header-contents ((,class ,@(modus-themes--syntax-string fg-dim fg-dim fg-dim fg-dim))))
`(wl-highlight-summary-answered-face ((,class ,@(modus-themes--syntax-string green-intense green-intense green-intense green-intense))))
`(wl-highlight-summary-deleted-face ((,class ,@(modus-themes--syntax-string blue-intense blue-intense blue-intense blue-intense))))
`(wl-highlight-summary-disposed-face ((,class ,@(modus-themes--syntax-string fg-dim fg-dim fg-dim fg-dim))))
`(wl-highlight-summary-flagged-face ((,class ,@(modus-themes--syntax-string yellow-intense yellow-intense yellow-intense yellow-intense))))
`(wl-highlight-summary-high-unread-face ((,class ,@(modus-themes--syntax-string red-intense red-intense red-intense red-intense))))
`(wl-highlight-summary-low-unread-face ((,class ,@(modus-themes--syntax-string red-intense red-intense red-intense red-intense))))
`(wl-highlight-summary-normal-face ((,class ,@(modus-themes--syntax-string fg-main fg-main fg-main fg-main))))
`(wl-highlight-summary-refiled-face ((,class ,@(modus-themes--syntax-string blue-alt blue-alt blue-alt blue-alt))))
`(wl-highlight-summary-spam-face ((,class ,@(modus-themes--syntax-string magenta-intense magenta-intense magenta-intense magenta-intense))))
`(wl-highlight-summary-thread-top-face ((,class ,@(modus-themes--syntax-string fg-main fg-main fg-main fg-main))))
`(wl-highlight-summary-unread-face ((,class ,@(modus-themes--syntax-string fg-main fg-main fg-main fg-main))))
;; `(wl-highlight-header-separator-face ((,class ,@(modus-themes--syntax-string fg-main fg-main fg-main fg-main))))
;; `(wl-highlight-logo-face ((,class ,@(modus-themes--syntax-string fg-main fg-main fg-main fg-main))))
;; `(wl-highlight-summary-copied-face ((,class ,@(modus-themes--syntax-string fg-main fg-main fg-main fg-main))))
`(wl-highlight-summary-displaying-face ((,class :underline t :bold t)))
;; `(wl-highlight-summary-resend-face ((,class ,@(modus-themes--syntax-string fg-main fg-main fg-main fg-main))))
;; `(wl-highlight-summary-prefetch-face ((,class ,@(modus-themes--syntax-string fg-main fg-main fg-main fg-main))))
;; `(wl-highlight-summary-target-face ((,class ,@(modus-themes--syntax-string fg-main fg-main fg-main fg-main))))
;; `(wl-highlight-summary-temp-face ((,class ,@(modus-themes--syntax-string fg-main fg-main fg-main fg-main))))
`(wl-highlight-summary-new-face ((,class ,@(modus-themes--syntax-string red-intense red-intense red-intense red-intense))))
;; `(wl-highlight-summary-killed-face ((,class ,@(modus-themes--syntax-string fg-main fg-main fg-main fg-main))))
;; `(wl-highlight-summary-low-read-face ((,class ,@(modus-themes--syntax-string fg-main fg-main fg-main fg-main))))
;; `(wl-highlight-thread-indent-face ((,class ,@(modus-themes--syntax-string fg-main fg-main fg-main fg-main))))
;; `(wl-highlight-summary-forwarded-face ((,class ,@(modus-themes--syntax-string fg-main fg-main fg-main fg-main))))
;; `(wl-highlight-summary-high-read-face ((,class ,@(modus-themes--syntax-string fg-main fg-main fg-main fg-main))))
;; `(wl-message-header-narrowing-face ((,class ,@(modus-themes--syntax-string fg-main fg-main fg-main fg-main))))
;; `(wl-summary-persistent-mark-face ((,class ,@(modus-themes--syntax-string fg-main fg-main fg-main fg-main))))
;;
)))
:advice
((:after
modus-themes-load-vivendi
my:set-background)
(:after
modus-themes-load-operandi
(lambda () (set-face-background 'default "#FFFFFF" )))
)
:hook
`((modus-themes-after-load-theme-hook
. (lambda ()
(my:modus-themes-custom-faces)
))
(window-setup-hook . my:set-background)
(tty-setup-hook . my:set-background)
)
:custom
`(
(modus-themes-inhibit-reload . t)
(modus-themes-success-deuteranopia . nil) ;; default
(modus-themes-bold-constructs . nil) ;; default
(modus-themes-italic-constructs . nil) ;; default
(modus-themes-syntax . '(alt-syntax green-strings))
(modus-themes-no-mixed-fonts . t)
(modus-themes-links . '(neutral-underline bold))
(modus-themes-prompts . '(intense bold))
(modus-themes-mode-line . '(borderless accented))
(modus-themes-tabs-accented . t)
(modus-themes-completions . nil) ;; default
(modus-themes-mail-citations . nil) ;; default
(modus-themes-fringes . nil) ;; default
(modus-themes-lang-checkers . '(straight-underline intense))
(modus-themes-hl-line . '(accented intense))
(modus-themes-subtle-line-numbers . nil) ;; default
(modus-themes-paren-match . '(bold intense))
(modus-themes-region . '(accented no-extend))
(modus-themes-diffs . nil) ;; default
(modus-themes-org-blocks . nil) ;; default
(modus-themes-org-agenda . '((t . nil)))
(modus-themes-headings . '((t . rainbow)))
(modus-themes-scale-headings . nil)
(modus-themes-variable-pitch-ui . nil)
(modus-themes-variable-pitch-headings . nil)
;; (modus-themes-vivendi-color-overrides
;; . '(
;; (bg-hl-line-intense-accent . "#556b2f")
;; ))
)
)
Debug&Test
(leaf rg
:if (executable-find "rg")
:ensure t
)
;;(leaf emacs
;; :preface
;; (defun my-advice/window-width (fn &rest args)
;; (- (apply fn args) 1))
;; :advice (:around window-width my-advice/window-width))
;;
;; (leaf elfeed
;; :if (file-directory-p my:d:password-store)
;; :ensure t
;; :custom
;; `((elfeed-set-timeout . 36000)
;; (elfeed-db-directory . "~/.cache/elfeed"))
;; :config
;; (leaf elfeed-goodies
;; :ensure t
;; :config
;; (elfeed-goodies/setup))
;; ;;
;; (leaf elfeed-protocol
;; :ensure t
;; :config
;; (setq elfeed-feeds
;; '(("owncloud+https://uwabami@uwabami.junkhub.org/nextcloud"
;; :password (password-store-get "Web/uwabami.junkhub.org/nextcloud")
;; )
;; ))
;; (elfeed-protocol-enable)
;; )
;; )
;;
(leaf vterm
:ensure t
:hook
(vterm-mode-hook
. (lambda () (setq-local global-hl-line-mode nil)))
)
(leaf keg :ensure t)
(leaf keg-mode :ensure t)
(leaf esup
:ensure t
:custom
((esup-insignificant-time . 0.01)
(esup-depth . 0)) ;; 🤔
)
起動時間の出力
(leaf *show-startup-time
:hook
(emacs-startup-hook
. (lambda ()
(message "init time: %.3f sec"
(float-time (time-subtract after-init-time before-init-time)))))
)
最後に
profiler report
これも必要に応じて
;; (profiler-report)
;; (profiler-stop)
provide の設定
(provide 'init)
;; Local Variables:
;; byte-compile-warnings: (not obsolete cl-functions)
;; End:
LICENSE
幾つかの関数の元ネタとして Emacs 本体のコードを参照したので, GPL-3 or later です.
Copyright (C) 2011--2017 Youhei SASAKI <uwabami@gfd-dennou.org> . This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. . This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. . You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.