emacs でお気に入りの設定 2025
目次
- 1. 環境
- 2. elpaca
- 3. ddskk
- 4. 標準機能のカスタマイズ
- 5. ediff
- 6. iserch でも C-h は DEL
- 7. whitespace の見え方
- 8. key-chord
- 9. shell-pop
- 10. 時を感じるで有名なやつ
- 11. smartrep をページャーとして
- 12. viewer-mode で色を変える
- 13. visual-replace
- 14. 昔の org-structure
- 15. org-agenda を q で閉じるだけ
- 16. ox-publish のオプション多すぎ
- 17. org-modern
- 18. mykie でクルクル移動
- 19. icons-in-terminal-dired で elc も emacs アイコンにする
- 20. ivy-with-migemo
- 21. 自作の小さな関数
1. 環境
- Ubuntu 24.04.1 LTS
- GNU Emacs 29.3 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.41, cairo version 1.18.0) of 2024-04-01, modified by Debian
2. elpaca
elpaca-manager を起動した時、省略せずに、一覧を一気に出したい
;; elpaca-manager で全てを一括で表示する (setq elpaca-ui-row-limit nil)
3. ddskk
3.1. ddskk の設定フォルダの変更
(setq skk-user-directory "~/.emacs.d/.ddskk")
3.2. azik の設定("~/.emacs.d/.ddskk/init")
超高速タイピング。
(setq skk-use-azik t)
3.3. stikey の設定("~/.emacs.d/.ddskk/init")
;; (setq skk-sticky-key [convert]) (setq skk-sticky-key [henkan])
3.4. 全角の入力
(setq skk-rom-kana-rule-list '(("z " nil " ")))
4. 標準機能のカスタマイズ
4.1. C-x C-c で容易にEmacsを終了させないように質問するようにする
(setq confirm-kill-emacs 'y-or-n-p)
4.2. ファイルパスからファイルを開く
(ffap-bindings)
4.3. なんか変なメーラ起動するのやめて
(global-set-key (kbd "C-c m") nil)
4.4. C-h はどこでも DEL
(define-key key-translation-map (kbd "C-h") (kbd "<DEL>"))
4.5. Scroll Lock は返してね
;; PC 切り換え機に割り当てるので (global-set-key (kbd "<Scroll_Lock>") 'ignore)
4.6. backup ファイルとかロックファイルとか、まとめてね
;; backup に 関する設定 ;; http://yohshiy.blog.fc2.com/blog-entry-319.html ;; バックアップファイル (foo.txt~) (setq backup-directory-alist '((".*" . "~/.emacs.d/backup/emacs-backup-files"))) ;; 番号付けによる複数保存 (setq version-control t) ;; 実行の有無 (setq kept-new-versions 10) ;; 最新の保持数 (setq kept-old-versions 10) ;; 最古の保持数 (setq delete-old-versions t) ;; 範囲外を削除 ;; 自動保存ファイル (#foo.txt#) (setq auto-save-file-name-transforms '((".*" "~/.emacs.d/backup/auto-saved-files" t))) ;; 保存の間隔 (setq auto-save-timeout 10) ;; 秒 (デフォルト : 30) (setq auto-save-interval 100) ;; 打鍵 (デフォルト : 300) ;; 自動保存リストファイル (~/.emacs.d/auto-save-list/.saves-xxxx) (setq auto-save-list-file-prefix "~/tmp/.saves-") ;; ロックファイル (.#foo.txt) ;; 作成しない (setq create-lockfiles nil)
5. ediff
(use-package ediff :ensure nil ;; Emacs標準のライブラリなので :ensure nil を指定 :init ;; ediff時に新しいフレームを作らない(シンプルになる) (setq ediff-window-setup-function 'ediff-setup-windows-plain) ;; diffのバッファを上下ではなく左右に並べる (setq ediff-split-window-function 'split-window-horizontally))
6. iserch でも C-h は DEL
(use-package isearch :ensure nil :bind (:map isearch-mode-map ("C-h" . isearch-del-char)))
7. whitespace の見え方
(use-package whitespace :ensure nil ;; whitespace は組み込みなので ensure は nil :commands (whitespace-mode) ;; コマンドをオートロードしたい場合に指定 :init ;; 基本的な変数設定などは :init で (setq whitespace-style '(face trailing tabs spaces lines lines-tail newline indentation::tab indentation::space indentation big-indent space-after-tab::tab space-after-tab::pace space-after-tab space-before-tab::tab space-before-tab::space space-before-tab tab-mark newline-mark)) ;; 全角スペースを可視化 (setq whitespace-space-regexp "\\(\u3000+\\)") :hook ;; 対象のモードで自動的に whitespace-mode を有効化 ((lisp-mode emacs-lisp-mode lisp-interaction-mode c-common-mode perl-mode python-mode org-mode markdown-mode) . whitespace-mode) :custom-face ;; custom-set-faces の代わりに :custom-face でまとめることが可能 (whitespace-big-indent ((t (:background "alice blue" :foreground "black")))) (whitespace-line ((t (:background "alice blue" :foreground "black")))) :config ;; さらに必要な設定を :config にまとめる (set-face-attribute 'whitespace-tab nil :foreground "light grey" :background 'unspecified :underline nil) (set-face-attribute 'whitespace-newline nil :foreground "light grey") (set-face-attribute 'whitespace-space nil :background "pink" :foreground 'unspecified :underline nil :weight 'bold))
8. key-chord
jkでview-modeに入る。もうちょっと活用できそうだけどなあ。
(use-package key-chord :ensure t :demand t :custom (key-chord-two-keys-delay 0.08) :init (key-chord-mode 1) :config (key-chord-define-global "jk" 'view-mode) ;; (key-chord-define-global "fn" 'open-junk-file) ;; (key-chord-define-global "fj" 'org-capture) )
9. shell-pop
f12がいい感じ
(use-package shell-pop :ensure t :bind ("<f12>" . shell-pop) :custom (shell-pop-shell-type '("eshell" "*eshell*" (lambda nil (eshell)))))
10. 時を感じるで有名なやつ
(use-package sky-color-clock :ensure (:host github :repo "tsuu32/sky-color-clock" :branch "master") :config (sky-color-clock-initialize 35) ; Tokyo, Japan (setq sky-color-clock-format "%Y-%m-%d (%a) %H:%M") (push '(:eval (sky-color-clock)) (default-value 'mode-line-format)) )
11. smartrep をページャーとして
(use-package smartrep :ensure t :init ;; C-l を一旦グローバルで未割り当てにする (global-unset-key (kbd "C-l")) :config ;; "C-l" に続くキー操作を smartrep で定義 (smartrep-define-key global-map "C-l" '(("h" . backward-char) ("l" . forward-char) ("j" . next-line) ("n" . next-line) ("k" . previous-line) ("p" . previous-line) ("b" . scroll-down) ("SPC" . scroll-up) ("f" . forward-word) ("e" . move-end-of-line) ("a" . move-beginning-of-line) ("J" . (lambda () (interactive) (scroll-up 1))) ("K" . (lambda () (interactive) (scroll-down 1))) ("g" . beginning-of-buffer) ("G" . end-of-buffer) ("r" . repeat) ("o" . open-line) ("C-l" . recenter-top-bottom))))
12. viewer-mode で色を変える
(use-package viewer :ensure t :config (viewer-stay-in-setup) (setq viewer-modeline-color-unwritable "tomato" viewer-modeline-color-view "orange") (viewer-change-modeline-color-setup) (setq view-mode-default-regexp "\\.ml$"))
13. visual-replace
ずっとvisual-regexpを使ってたけど、今回乗り変えた。
(use-package visual-replace :defer t :hook ;; Visual Replaceのミニバッファが立ち上がったら、 ;; 自動でクエリモードに切り替える (visual-replace-minibuffer-mode . visual-replace-toggle-query) :bind (("C-c r" . visual-replace) :map isearch-mode-map ("C-c r" . visual-replace-from-isearch)))
14. 昔の org-structure
(use-package org-tempo :ensure nil :after org :config (add-to-list 'org-structure-template-alist '("el" . "src elisp")) (add-to-list 'org-structure-template-alist '("py" . "src python")) (add-to-list 'org-structure-template-alist '("sh" . "src shell")))
15. org-agenda を q で閉じるだけ
(use-package org-agenda :ensure nil :after org :bind (:map org-agenda-mode-map ("q" . quit-window)) )
16. ox-publish のオプション多すぎ
;; ---------------------------------------- ;; 6. Org Export: ox-publish ;; ---------------------------------------- (use-package ox-publish :after org :ensure nil :config (setq org-publish-project-alist '(("gitpages-org" ;; 1) 必須設定 ------------------------------------- :base-directory "~/clothoid.github.io/clothoid.github.io/org/" ;; ソース (Org) ファイルのあるディレクトリ :base-extension "org" ;; 対象となるファイル拡張子 :publishing-directory "~/clothoid.github.io/clothoid.github.io/docs/" ;; 出力先ディレクトリ :publishing-function org-html-publish-to-html ;; HTML に変換する関数 :recursive t ;; サブディレクトリを再帰的に処理するかどうか ;; 2) よく使う基本オプション ------------------------- :headline-levels 4 ;; 見出しを何階層まで出力するか :auto-preamble t ;; テンプレート(プレアンブル)を自動挿入 ;; :auto-postamble t ;; ポストアンブルを自動挿入 (デフォルト t) ;; :auto-index t ;; (古いオプション) インデックス生成を自動化 (Org 9.0以降は推奨されていない) :auto-sitemap t ;; サイトマップ (目次) の自動生成 :sitemap-title "site map" ;; サイトマップのタイトル :sitemap-style list ;; サイトマップの形式: `list` か `tree` か `random` :sitemap-sort-files anti-chronologically ;; ファイルを新しい順にソート ;; :sitemap-sort-folders nil ;; サブディレクトリのソート (nil, first, last) ;; :sitemap-filename "sitemap.org" ;; サイトマップファイル名 ;; :sitemap-file-entry-format "%t" ;; サイトマップでのエントリ表示形式 (%t=タイトル, %f=ファイル名, など) ;; :sitemap-date-format "%Y-%m-%d" ;; 日付の表示形式 ;; :sitemap-ignore-case nil ;; 大文字小文字を無視してソートするかどうか ;; :sitemap-exclude "Private" ;; この正規表現にマッチするファイルをサイトマップに含めない ;; :sitemap-function nil ;; カスタムでサイトマップを生成したい場合の関数 ;; :sitemap-format-entry nil ;; 各エントリのフォーマット関数 ;; 3) HTML 出力オプション -------------------------- :html_link_up "index.html" ;; アップリンク用 (上位ページへのリンク) :html_link_home "index.html" ;; ホームリンク用 ;; :html_doctype "html5" ;; <!DOCTYPE html> の種類 (例: "html5") ;; :html_extension "html" ;; 出力ファイルの拡張子 ;; :html_head "<link rel=\"stylesheet\" href=\"style.css\" />" ;; <head> に追加する要素 ;; :html_head_include_default_style t ;; Org デフォルトの CSS を含めるかどうか ;; :html_head_include_scripts t ;; Org デフォルトのスクリプトを含めるかどうか ;; :html_preamble nil ;; HTML の <body> 内、本文開始前に挿入する内容 ;; :html_postamble nil ;; HTML の <body> 内、本文終了後に挿入する内容 ;; :htmlized_source t ;; ソースブロックを HTML のソース表示にするかどうか ;; :inline-css nil ;; HTML 内に CSS をインラインで埋め込むかどうか (古いオプション) ;; :style "<link rel=\"stylesheet\" type=\"text/css\" href=\"mystyle.css\"/>" ;; 古い形式でのスタイル指定 (Org 8 以前) ;; :style-include-default nil ;; 古い形式でのデフォルト CSS を含めるかどうか ;; :style-include-scripts nil ;; 古い形式でのデフォルトスクリプトを含めるかどうか ;; 4) Table of Contents, 見出し番号など ------------ ;; :with-toc t ;; 目次を表示するかどうか ;; :section-numbers t ;; 見出し番号を付与するかどうか ;; :table-of-contents t ;; :with-toc の別名 ;; :preserve-breaks nil ;; 改行をHTMLでも改行として扱うかどうか ;; :with-author t ;; 著者名の出力 ( #+AUTHOR: など ) ;; :with-creator t ;; "Created by Org ..." のメタ情報を出力するか ;; :with-email t ;; メールアドレスの出力 ( #+EMAIL: など ) ;; :with-footnotes t ;; 脚注を出力するか ;; :with-latex t ;; LaTeX 数式を変換 (デフォルト: t) ;; :with-sub-superscript t ;; ^ や _ 記号の上付き・下付き処理 ;; 5) 細かい制御オプション -------------------------- ;; :exclude "PrivateOrgFile.org" ;; 発行対象から除外するファイルを指定(正規表現) ;; :include ("some.org") ;; 発行対象に含めるファイルを明示的に指定 ;; :makeindex t ;; 索引ファイルを作る (古い方式) ;; :index-style 'inline ;; 索引のスタイル (inline, fancy) ;; :timestamp nil ;; ファイルの先頭にタイムスタンプを付加するか ) ("gitpages-files" :base-directory "~/clothoid.github.io/clothoid.github.io/org/" :publishing-directory "~/clothoid.github.io/clothoid.github.io/docs/" :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf" :recursive t :publishing-function org-publish-attachment ;; :exclude "secret.png" ;; :include ("somefile.css") ) ("gitpages" :components ("gitpages-org" "gitpages-files")))) (message "ox-publish loaded."))
17. org-modern
おしゃれにしたいよ。
(use-package org-modern :defer t :after org :hook (org-mode . org-modern-mode) :config ;; org-modern をグローバルに有効化 (global-org-modern-mode) ;; https://misohena.jp/blog/2022-08-27-fix-org-table-lines-using-org-modern-and-org-indent.html ;; org-indentを使っていると表の水平線の高さが狭まらない問題を修正する。 ;; インデントの空白文字列をdisplayプロパティで高さ1pxのspaceに置き換える。 (defun my-org-indent--compute-prefixes-after () (let ((prefixes org-indent--text-line-prefixes)) (dotimes (i (length prefixes)) (let* ((space-str (aref prefixes i)) (space-length (length space-str))) (when (> space-length 0) (aset prefixes i (org-add-props space-str nil 'display (cons 'space (list :width space-length :height '(1)))))))))) (advice-add #'org-indent--compute-prefixes :after #'my-org-indent--compute-prefixes-after) ;; org-modern--table を差し替え (defun org-modern--table () "Prettify vertical table lines." (save-excursion (let* ((beg (match-beginning 0)) (end (match-end 0)) (tbeg (match-beginning 1)) (tend (match-end 1)) ;; Unique objects (sp1 (list 'space :width 1)) (sp2 (list 'space :width 1)) (color (face-attribute 'org-table :foreground nil t)) (inner (progn (goto-char beg) (forward-line) (re-search-forward "^[ \t]*|" (line-end-position) t))) (separator (progn (goto-char beg) (re-search-forward "^[ \t]*|-" end 'noerror)))) ;; 横線を引く (goto-char beg) (when separator ;; overline を引いて高さを縮める (when (numberp org-modern-table-horizontal) (add-face-text-property tbeg tend `(:overline ,color) 'append) (add-face-text-property beg (1+ end) `(:height ,org-modern-table-horizontal) 'append)) (while (re-search-forward "[^|+]+" tend 'noerror) (let ((a (match-beginning 0)) (b (match-end 0))) (cl-loop for i from a below b do (put-text-property i (1+ i) 'display (if (= 0 (mod i 2)) sp1 sp2)))))) ;; 縦線を引く (goto-char beg) (while (re-search-forward "-+\\(?1:+\\)-\\|\\(?:^\\|[- ]\\)\\(?1:|\\)\\(?:$\\|[- ]\\)" end 'noerror) (let ((a (match-beginning 1)) (b (match-end 1))) (cond ((and org-modern-table-vertical (or (not separator) inner)) (add-text-properties a b `(display " " face (:inherit org-table :inverse-video t))) ;; 高さを小さくする (ピクセル単位指定のため厳密な制御は困難) (add-face-text-property a b `(:height 0.1) 'append)) ((and org-modern-table-horizontal separator) (put-text-property a b 'display " ")) (t (put-text-property a b 'face 'org-hide)))))))))
18. mykie でクルクル移動
死ぬほど使ってる。。。なんでだろ。
(use-package mykie :ensure t :config ;; :region&repeat を mykie:region-conditions に追加 (push '(:region&repeat . (mykie:repeat-p)) mykie:region-conditions) ;; seq-home/seq-end 相当の機能で使う変数 (defvar mykie-seq-point nil) ;; "C-a" に対する mykie の設定 (mykie:global-set-key "C-a" :default (progn (setq mykie-seq-point (point)) (beginning-of-line)) :repeat (cond ((bobp) (goto-char mykie-seq-point)) ((bolp) (beginning-of-buffer)) (t (beginning-of-line)))) ;; "C-e" に対する mykie の設定 (mykie:global-set-key "C-e" :default (progn (setq mykie-seq-point (point)) (end-of-line)) :repeat (cond ((eobp) (goto-char mykie-seq-point)) ((eolp) (end-of-buffer)) (t (end-of-line)))) (mykie:global-set-key "C-t" :default (progn (when (one-window-p) (split-window-horizontally)) (other-window 1))) )
19. icons-in-terminal-dired で elc も emacs アイコンにする
;; 1. icons-in-terminal-dired を使う場合の設定 (use-package icons-in-terminal-dired :ensure (icons-in-terminal-dired :repo "takaxp/icons-in-terminal-dired" :host github) :if (display-graphic-p) ;; GUI環境のみ使う場合 :hook (dired-mode . icons-in-terminal-dired-mode)) ;; 2. icons-in-terminal のアイコンルールを上書きする例 (with-eval-after-load 'icons-in-terminal ;; まずは ".elc" 用の既存ルールを削除 (いったんアイコンを消す) (setq icons-in-terminal-icon-alist (cl-remove-if (lambda (it) (string= (car it) "\\.elc")) icons-in-terminal-icon-alist)) ;; そして改めて ".elc" 用を好きなアイコンで再登録 (add-to-list 'icons-in-terminal-icon-alist '("\\.elc" icons-in-terminal-fileicon "elisp" :height 1.0 :v-adjust -0.2 :face icons-in-terminal-purple)) 0) ;; 注意 ;; icons-in-terminal は icons-in-terminal-icon-alist のエントリを上から順に正規表現マッチして、 ;; 一番最初にヒットしたものを使う仕組み。 ;; デフォルト設定に ;; 「`_test.`(または `-test.`)が含まれるファイル名はテストファイル扱いにして `test-generic` のアイコンを表示する」 ;; というルールが入っている ;; `999_test.el` が先にそのパターンにマッチしてしまい、「テストファイル用アイコン」になってしまう
20. ivy-with-migemo
ありがてえ、ありがてえ。。。
(use-package ivy-with-migemo :ensure (:repo "https://gist.github.com/tam17aki/256094b57faad19d60eed7761c351d5b.git" ;; Gist の中で必要なファイルがこれだけなら指定 :files ("ivy-with-migemo.el")) :init ;; パッケージ読み込み前に設定しておきたい変数は :init に書く (setq ivy-with-migemo-enable-command '(swiper swiper-isearch counsel-recentf counsel-rg ivy-switch-buffer counsel-locate)) (setq migemo-options '("--quiet" "--nonewline" "--emacs")) :config ;; パッケージ読み込み後に実行する設定 ;; (require 'migemo) ;; migemo-kill, migemo-initを呼ぶために require しておく (migemo-kill) (migemo-init) (global-ivy-with-migemo-mode 1) (message "ivy-with-migemo.el loaded") )
21. 自作の小さな関数
21.1. markdown から org へ変換
ChatGPTもFeloもmarkdownコピーなので。。。要pandoc
;;; markdown-to-org.el --- Convert Markdown to Org-mode format using pandoc ;; Copyright (C) 2023 Your Name ;; Author: Your Name <your.name@example.com> ;; URL: https://github.com/yourname/markdown-to-org ;; Version: 0.1.0 ;; Keywords: markdown, org-mode, pandoc, convert ;; Package-Requires: ((emacs "24.4")) ;; License: MIT ;;; Commentary: ;; ;; This package provides functions to convert Markdown text into Emacs ;; org-mode text by using pandoc. You can use it in a buffer, region, or ;; an external file. ;;; Code: (defgroup markdown-to-org nil "Convert Markdown to Org-mode with pandoc." :group 'tools :prefix "markdown-to-org-") (defcustom markdown-to-org-pandoc-path "pandoc" "Path to the pandoc command." :type 'string :group 'markdown-to-org) (defun markdown-to-org--run-pandoc (beg end) "Run pandoc on the region between BEG and END to convert Markdown to Org." (let ((pandoc-cmd (format "%s -f markdown -t org" markdown-to-org-pandoc-path))) (shell-command-on-region beg end pandoc-cmd ;; Insert results in current buffer, replacing the region t ;; Output buffer t))) ;;;###autoload (defun markdown-to-org-convert-region (beg end) "Convert the Markdown in region (BEG to END) to Org-mode in-place." (interactive "r") (markdown-to-org--run-pandoc beg end) (message "Converted Markdown region to Org-mode!")) ;;;###autoload (defun markdown-to-org-convert-buffer () "Convert the entire buffer from Markdown to Org-mode." (interactive) (markdown-to-org--run-pandoc (point-min) (point-max)) (message "Converted entire buffer from Markdown to Org-mode!")) ;;;###autoload (defun markdown-to-org-convert-file (input-file output-file) "Convert INPUT-FILE (Markdown) to OUTPUT-FILE (Org-mode) using pandoc." (interactive "fMarkdown file to convert: \nFOutput Org file: ") (let ((pandoc-cmd (format "%s -f markdown -t org %s -o %s" markdown-to-org-pandoc-path (shell-quote-argument (expand-file-name input-file)) (shell-quote-argument (expand-file-name output-file))))) (shell-command pandoc-cmd) (message "Converted %s to %s" input-file output-file))) (provide 'markdown-to-org) ;;; markdown-to-org.el ends here
21.2. 時間と日付のコピー
;; -*- Mode: Emacs-Lisp ; Coding: utf-8 -*- (require 'org) ;; 時間をコピーする (defun copy-time () "現在時間をキルリングにセットする" (interactive) (kill-new (format-time-string "%Y-%m-%d-%H%M%S_"))) (defun get-date () (interactive) (let ((org-time-stamp-formats org-time-stamp-custom-formats)) (org-insert-time-stamp (current-time) nil))) (defun get-dtime () (interactive) (let ((org-time-stamp-formats org-time-stamp-custom-formats)) (org-insert-time-stamp (current-time) t))) (provide 'get-and-copy-time-and-date)
21.3. 透過の設定を interactive に変更
; -*- Mode: Emacs-Lisp ; Coding: utf-8 -*- ;;; フレームを半透明にする ;; (set-frame-parameter nil 'alpha 75) (defun frame-transparency (n) "alphaをnに変更する" (interactive "n value: ") (set-frame-parameter nil 'alpha n)) (provide 'frame-transparency)
21.4. 行コピー
標準でありそうだけど…
;; -*- Mode: Emacs-Lisp ; Coding: utf-8 -*- ;; 現在行をコピーして下の行に貼り付ける (defun duplicate-this-line-forward (n) "Duplicates the line point is on. The point is next line. With prefix arg, duplicate current line this many times." (interactive "p") (when (eq (point-at-eol)(point-max)) (save-excursion (end-of-line) (insert "\n"))) (save-excursion (beginning-of-line) (dotimes (i n) (insert-buffer-substring (current-buffer) (point-at-bol)(1+ (point-at-eol)))))) (provide 'duplicate-this-line-forward)
21.5. OS連携1
;;; my-dired-extensions.el --- 自作 Dired 拡張や OS 連携 ;;; Code: (require 'dired) ;; dired を拡張するので一応読み込む (require 'cl-lib) (require 'recentf) ;;---------------------------------------- ;; OS 判定 & OS ごとにファイルを開くコマンドを決定するコード ;;---------------------------------------- (defun os-type () "現在の OS タイプを返す (cygwin, linux, darwin など)." (let ((uname-str (shell-command-to-string "uname"))) (cond ((string-match "CYGWIN" uname-str) 'cygwin) ((string-match "Linux" uname-str) 'linux) ((string-match "Darwin" uname-str) 'darwin)))) (defun os-open-command-name (os-type) "OS-TYPE に応じて実行できるファイルオープンコマンドのパスを探す." (let ((command-name-list (cl-case os-type ('cygwin '("sglstart" "cygstart")) ('linux '("sglstart" "wslstart" "xdg-open" "gnome-open")) ('darwin '("open"))))) (catch 'loop (dolist (command-name command-name-list) (let* ((command1 (concat "which " command-name " 2> /dev/null")) (command2 (if (file-remote-p default-directory) ;; リモートではログインシェルでコマンドを実行する (format "$0 -l -c '%s' 2> /dev/null" command1) command1)) (absolute-path-command-name (replace-regexp-in-string "\n" "" (shell-command-to-string command2)))) (unless (string= absolute-path-command-name "") (throw 'loop absolute-path-command-name))))))) ;; コマンド名をホストごとにキャッシュ (defvar os-open-command-cache nil "ホスト名をキーにして (OS-TYPE OS-OPEN-COMMAND-NAME) を保持するキャッシュ変数.") (defun os-open-command-cache () "ホストごとのコマンドキャッシュを返す." (let* ((hostname (if (file-remote-p default-directory) (let* ((vec (tramp-dissect-file-name default-directory)) (host (tramp-file-name-host vec)) (user (tramp-file-name-user vec))) (if user (format "%s@%s" user host) host)) "<localhost>"))) (cdr (or (assoc hostname os-open-command-cache) (let* ((type (os-type)) (cmd (os-open-command-name type))) (car (push (cons hostname (list type cmd)) os-open-command-cache))))))) ;;---------------------------------------- ;; OS で直接ファイルを開く ;;---------------------------------------- (defun os-open-command (filename) "FILENAME を OS のコマンドで開く." (interactive "FOpen file: ") (let* ((filename (expand-file-name filename)) (default-directory (file-name-directory filename))) (let* ((cache (os-open-command-cache)) (type (nth 0 cache)) (cmd (nth 1 cache))) (if cmd (let ((localname (if (file-remote-p filename) (tramp-file-name-localname (tramp-dissect-file-name filename)) filename))) (message "%s %s" (file-name-nondirectory cmd) localname) (cond ((and (eq type 'linux) (not (file-remote-p default-directory))) ;; Linux + ローカル環境 (let (process-connection-type) (start-process "os-open-command" nil cmd localname))) (t ;; リモートでも使えるように shell-command-to-string (shell-command-to-string (format "%s %s &" cmd (shell-quote-argument localname)))))) (message "利用できるコマンドがありません。"))))) (defun os-open-command-2 (filename) "FILENAME を recentf に登録してから OS で開く." (interactive "FOpen file with recentf: ") (recentf-push filename) (os-open-command filename)) ;;---------------------------------------- ;; Dired でキー操作・マウス操作をしたとき OS で開く ;;---------------------------------------- (define-key dired-mode-map (kbd "W") (lambda () (interactive) (os-open-command-2 (dired-get-file-for-visit)))) (define-key dired-mode-map [mouse-2] (lambda (event) (interactive "e") (dired-mouse-find-file event 'os-open-command-2 'os-open-command-2))) (define-key dired-mode-map (kbd "E") (lambda () (interactive) (os-open-command (dired-current-directory)))) (define-key dired-mode-map [mouse-3] (lambda (event) (interactive "e") (mouse-select-window event) (os-open-command (dired-current-directory)))) ;;---------------------------------------- ;; OS で開きたいファイルの拡張子リスト & find-file のアドバイス ;;---------------------------------------- (setq os-open-file-suffixes '("doc" "docx" "xls" "xlsx" "ppt" "pptx" "mdb" "mdbx" "vsd" "vdx" "vsdx" "mpp" "pdf" "bmp" "jpg" "odt" "ott" "odg" "otg" "odp" "otp" "ods" "ots" "odf")) (defun os-open-file-p (filename) "FILENAME が os-open-file-suffixes の拡張子を持つ通常ファイルなら t." (when (file-regular-p filename) (let ((ext (file-name-extension filename))) (when (and ext (member (downcase ext) os-open-file-suffixes)) t)))) (advice-add 'find-file :around (lambda (orig-fun &rest args) (let* ((file-name (nth 0 args)) (target-name (or (file-symlink-p file-name) file-name))) (if (os-open-file-p target-name) (os-open-command-2 target-name) (apply orig-fun args))))) ;;---------------------------------------- ;; dired-guess-shell の設定 ;;---------------------------------------- (setq dired-guess-shell-alist-user '(("\\.doc$" (nth 1 (os-open-command-cache))) ("\\.docx$" (nth 1 (os-open-command-cache))) ("\\.xls$" (nth 1 (os-open-command-cache))) ("\\.xlsx$" (nth 1 (os-open-command-cache))) ("\\.ppt$" (nth 1 (os-open-command-cache))) ("\\.pptx$" (nth 1 (os-open-command-cache))) ("\\.mdb$" (nth 1 (os-open-command-cache))) ("\\.mdbx$" (nth 1 (os-open-command-cache))) ("\\.vsd$" (nth 1 (os-open-command-cache))) ("\\.vdx$" (nth 1 (os-open-command-cache))) ("\\.vsdx$" (nth 1 (os-open-command-cache))) ("\\.mpp$" (nth 1 (os-open-command-cache))) ("\\.pdf$" (nth 1 (os-open-command-cache))) ("\\.bmp$" (nth 1 (os-open-command-cache))) ("\\.odt$" (nth 1 (os-open-command-cache))) ("\\.ott$" (nth 1 (os-open-command-cache))) ("\\.odg$" (nth 1 (os-open-command-cache))) ("\\.otg$" (nth 1 (os-open-command-cache))) ("\\.odp$" (nth 1 (os-open-command-cache))) ("\\.otp$" (nth 1 (os-open-command-cache))) ("\\.ods$" (nth 1 (os-open-command-cache))) ("\\.ots$" (nth 1 (os-open-command-cache))) ("\\.odf$" (nth 1 (os-open-command-cache))))) ;;---------------------------------------- ;; Dired を 2つのウィンドウで開いているときに ;; other-window へ copy/move/symlink する ;;---------------------------------------- (defun dired-do-copy-dwim () (interactive) (let ((dired-dwim-target t)) (dired-do-copy))) (defun dired-do-rename-dwim () (interactive) (let ((dired-dwim-target t)) (dired-do-rename))) (defun dired-do-symlink-dwim () (interactive) (let ((dired-dwim-target t)) (dired-do-symlink))) (define-key dired-mode-map (kbd "c") 'dired-do-copy-dwim) (define-key dired-mode-map (kbd "r") 'dired-do-rename-dwim) (define-key dired-mode-map (kbd "s") 'dired-do-symlink-dwim) (define-key dired-mode-map (kbd "e") 'wdired-change-to-wdired-mode) ;; dired-start-eshell を別の関数に remap (define-key dired-mode-map [remap dired-do-shell-command] 'dired-start-eshell) (provide 'dired-extensions) ;;; dired-extensions.el ends here
21.6. バッファ名をコピー
標準でありそうだけど、見つからず…
;; -*- Mode: Emacs-Lisp ; Coding: utf-8 -*- ;; バッファ名をコピーする (defun copy-buffer-name () (interactive) (kill-new (buffer-name))) ;; フルパスをコピーする (defun copy-fullpath-buffer-file-name () "カレントバッファのファイル名 (フルパス) をコピー" (interactive) (if buffer-file-name (progn (kill-new buffer-file-name) (message buffer-file-name)) (message "ファイルじゃありません"))) (provide 'copy-buffer-name)
21.7. 現在のバッファとファイル名を同時に変更
; -*- Mode: Emacs-Lisp ; Coding: utf-8 -*- ;; source: http://steve.yegge.googlepages.com/my-dot-emacs-file (defun rename-file-and-buffer (new-name) "Renames both current buffer and file it's visiting to NEW-NAME." (interactive "sNew name: ") (let ((name (buffer-name)) (filename (buffer-file-name))) (if (not filename) (message "Buffer '%s' is not visiting a file!" name) (if (get-buffer new-name) (message "A buffer named '%s' already exists!" new-name) (progn (rename-file filename new-name 1) (rename-buffer new-name) (set-visited-file-name new-name) (set-buffer-modified-p nil)))))) (provide 'rename-file-and-buffer)
21.8. 自動確固挿入
smart paren がうまく動かなくなったので..
;; -*- Mode: Emacs-Lisp ; Coding: utf-8 -*- (defvar wrap-pairs-alist '(( "(" . ")") ( "[" . "]") ( "{" . "}") ( "<" . ">") ( "\"" . "\"") ( "'" . "'"))) (defun get-right-wrap (left-wrap) "左の囲み文字から右の囲み文字を取得する。" (cdr (assoc left-wrap wrap-pairs-alist))) (defun wrap-region-with-auto-right (start end left-wrap) "リージョンを指定された囲み文字で囲む。右の囲み文字は左の囲み文字から自動で類推される。" (let* ((right-wrap (get-right-wrap left-wrap)) (end-marker (set-marker (make-marker) end))) (save-excursion (goto-char start) (insert left-wrap) (goto-char (marker-position end-marker)) (insert (or right-wrap ""))) (set-marker end-marker nil))) ; マーカーをクリーンアップ (defun wrap-region-or-insert (left-wrap) "リージョンが選択されていればリージョンを指定された囲み文字で囲む。 リージョンが選択されていなければ囲み文字を挿入し、カーソルを囲み文字の間に移動する。" (interactive) (if (use-region-p) (wrap-region-with-auto-right (region-beginning) (region-end) left-wrap) (let ((right-wrap (get-right-wrap left-wrap))) (insert left-wrap (or right-wrap "")) (backward-char (length (or right-wrap ""))))) (deactivate-mark)) ; リージョンの選択を解除 (provide 'wrap-region-or-insert)
21.9. os のバージョン
(defun get-os-version () "Return a string describing the OS version." (cond ;; macOS ((eq system-type 'darwin) (string-trim (shell-command-to-string "sw_vers -productVersion"))) ;; Linux ((eq system-type 'gnu/linux) (or ;; まずは lsb_release があればそれを使う (let ((lsb (executable-find "lsb_release"))) (when lsb (string-trim (shell-command-to-string (concat lsb " -d | cut -f2-"))))) ;; なければ /etc/os-release を試す (when (file-readable-p "/etc/os-release") (with-temp-buffer (insert-file-contents "/etc/os-release") (goto-char (point-min)) (if (re-search-forward "^PRETTY_NAME=\"\\(.*?\\)\"" nil t) (match-string 1) "Unknown Linux distribution"))) ;; 最後の手段: uname -r などで kernel version を返す (string-trim (shell-command-to-string "uname -r")))) ;; Windows ((eq system-type 'windows-nt) (string-trim (shell-command-to-string "ver"))) ;; 上記以外 (t "Unknown OS"))) (defun os-version () "Display the OS version in *Messages*." (interactive) (message "Your OS version: %s" (get-os-version)))
21.10. その他
雑誌やメルマガに掲載されていたものは、そのまま書けないな。。。
- view-mode-pager.el
- view-mode では、vi ライクな閲覧モード
- yes-or-no-p.el
- yes/no を y/n で
脚注:
1
Windows ネイティブ版があったはずだけど、wsl2 に移行してから、どっかいってしまった。探してみよう。。。