Emacsのインストール、設定、操作ガイド(Windows・Linux対応)

【概要】Emacsはテキストエディタである。WindowsとUbuntuでインストール方法が異なる。WindowsではwingetでEmacsをインストールできる。Ubuntuではaptでインストールできる。オプションとして、フォント、Pythonのインストールも紹介している。さらに、Emacsの設定ファイルinit.elとして、Python、HTML、CSS、テキストファイル編集用の機能を設定したinit.elファイルのサンプルも示している(その全機能を使うには、追加でblack、isort、python-lsp-serverのインストールが必要であり、その手順も示している)。基本編集操作、メジャーモード、マイナーモード、トラブルシューティングの説明も行っている。

Emacsの画面例

【Emacsの基本操作の要点】Emacsでは、カーソル移動(Ctrl+p/n/f/b)、テキスト編集(Ctrl+k/y)、ファイル操作(Ctrl+x Ctrl+f/s)、検索(Ctrl+s)、バッファ管理(Ctrl+x Ctrl+b)、ウィンドウ分割(Ctrl+x 2/1)、リージョン指定(Ctrl+Space)が可能である。

目次

  1. Emacsの基本の要点
  2. Emacs設定ガイド(Windows・Linux対応)
  3. Windows環境での設定
  4. Ubuntu環境での設定
  5. init.el設定(Windows・Linux対応)
  6. Emacsの基本編集機能のガイド
  7. 設定後の確認方法
  8. トラブルシューティング

Emacsの基本の要点

キーバインド表記について

Emacsでは、以下の表記方法を用いてキーバインドを示す。

Emacsの基本概念

Emacsを理解するために、以下の基本概念を把握することが重要である。

Emacs設定ガイド(Windows・Linux対応)

コマンド実行について

Windows環境

Windows環境では、管理者権限でコマンドプロンプトを起動する必要がある。Windowsキーを押し、cmdと入力した後、右クリックして「管理者として実行」を選択する。

Ubuntu環境

Ubuntu環境では、ターミナルを開く必要がある。Ctrl+Alt+Tを押すか、アプリケーションメニューから「ターミナル」を選択する。

Windows環境での設定

Emacsインストールコマンド(Windowsのみ)

管理者権限でコマンドプロンプトを起動し(Windowsキー > cmd と入力 > 右クリック > 「管理者として実行」)、以下を実行する。

emacs-30.1」のところは、実際にインストールしたバージョンに合わせること。

winget install --scope machine GNU.Emacs
REM Emacsのパス
set "INSTALL_PATH=C:\Program Files\Emacs\emacs-30.1\bin"
echo ;%PATH%; | find /i ";%INSTALL_PATH%;" >nul
if errorlevel 1 setx PATH "%PATH%;%INSTALL_PATH%" /M >nul

Pythonのインストールコマンド(Windowsのみ)

インストール済みの場合は実行不要である。

管理者権限でコマンドプロンプトを起動し(Windowsキー > cmd と入力 > 右クリック > 「管理者として実行」)、以下を実行する(wingetコマンドは1つずつ実行する)。

REM Pythonをシステム領域にインストール
winget install --scope machine --id Python.Python.3.12 -e --silent
REM Pythonのパス設定
set "PYTHON_PATH=C:\Program Files\Python312"
set "PYTHON_SCRIPTS_PATH=C:\Program Files\Python312\Scripts"
echo "%PATH%" | find /i "%PYTHON_PATH%" >nul
if errorlevel 1 setx PATH "%PATH%;%PYTHON_PATH%" /M >nul
echo "%PATH%" | find /i "%PYTHON_SCRIPTS_PATH%" >nul
if errorlevel 1 setx PATH "%PATH%;%PYTHON_SCRIPTS_PATH%" /M >nul

Python開発環境のセットアップ(Windowsのみ)

管理者権限でコマンドプロンプトを起動し(Windowsキー > cmd と入力 > 右クリック > 「管理者として実行」)、以下を実行する。

pip install black isort python-lsp-server[all]

DPIスケーリング無効化の設定(Windowsのみ)

管理者権限でコマンドプロンプトを起動し(Windowsキー > cmd と入力 > 右クリック > 「管理者として実行」)、以下を実行する。

emacs-30.1」のところは、実際にインストールしたバージョンに合わせること。

REG ADD "HKCU\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers" /v "C:\Program Files\Emacs\emacs-30.1\bin\emacs.exe" /t REG_SZ /d "~ DPIUNAWARE" /f
REG ADD "HKCU\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers" /v "C:\Program Files\Emacs\emacs-30.1\bin\runemacs.exe" /t REG_SZ /d "~ DPIUNAWARE" /f

フォント設定(Windowsのみ)

管理者権限でコマンドプロンプトを起動し(Windowsキー > cmd と入力 > 右クリック > 「管理者として実行」)、以下を実行する。

cd %HOMEPATH%
curl -L -O https://github.com/yuru7/HackGen/releases/download/v2.10.0/HackGen_NF_v2.10.0.zip
powershell Expand-Archive -Path HackGen_NF_v2.10.0.zip -DestinationPath HackGen_NF_v2.10.0
copy "HackGen_NF_v2.10.0\HackGen_NF_v2.10.0\HackGenConsoleNF-Bold.ttf" "%WINDIR%\Fonts\"
copy "HackGen_NF_v2.10.0\HackGen_NF_v2.10.0\HackGenConsoleNF-Regular.ttf" "%WINDIR%\Fonts\"

echo REGEDIT4 > font.reg
echo. >> font.reg
echo [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts] >> font.reg
echo "HackGenConsoleNF Regular (TrueType)"="HackGenConsoleNF-Regular.ttf" >> font.reg
echo "HackGenConsoleNF Bold (TrueType)"="HackGenConsoleNF-Bold.ttf" >> font.reg
regedit /s font.reg

Ubuntu環境での設定

PythonとEmacsのインストールコマンド(Ubuntuのみ)

ターミナルを開き、以下を実行する。

# システムの更新
sudo apt update && sudo apt upgrade -y

# Python3と開発環境のインストール
sudo apt install -y python3 python3-pip python3-venv python3-dev build-essential

# Emacsのインストール
sudo apt install -y emacs

# 日本語入力のためのインストール
sudo apt install -y fcitx5-mozc fonts-noto-cjk

フォント設定(Ubuntuのみ)

ターミナルを開き、以下を実行する。

# HackGenフォントのダウンロードとインストール
wget https://github.com/yuru7/HackGen/releases/download/v2.10.0/HackGen_v2.10.0.zip
unzip HackGen_v2.10.0.zip
mkdir -p ~/.local/share/fonts
cp HackGen_v2.10.0/HackGen-Regular.ttf ~/.local/share/fonts/
fc-cache -fv

# 代替フォント(Noto Sans Mono CJK JP)のインストール
sudo apt install fonts-noto-cjk

Python開発環境のセットアップ(Ubuntuのみ)

ターミナルを開き、以下を実行する。

# Pythonパッケージのインストール
pip3 install black isort python-lsp-server[all]

補足事項(Ubuntuのみ)

Ubuntu環境では、フォントの優先順位としてNoto Sans Mono CJK JP(推奨)、Noto Sans(フォールバック)を使用する。日本語入力については、init.elのLinux設定は基本的なものであり、必要に応じてfcitx5やiBus等の設定が別途必要となる。

init.el設定(Windows・Linux対応)

次のファイルを編集する。

;;; init.el --- Emacs configuration for Windows and Linux -*- lexical-binding: t -*-

;;; Commentary:

;; Personal Emacs configuration for Windows and Linux.
;; Supports Python, HTML, Markdown editing with Eglot, syntax checking,
;; Japanese/English input, and cross-platform font handling.
;;
;; 2025年修正版の主な変更点:
;; - Emacs 30.1対応
;; - lsp-modeからeglot(標準搭載)への移行
;; - Ubuntu 24.04のfcitx5-mozc対応
;; - tr-ime 0.5.0対応
;; - パッケージインストールの安定化
;; - 日本語入力自動切り替えの制御変更(advice-add修正)

;;; Code:

;; --------------------
;; 1. 設定定数
;; --------------------

;; OS判別関数
(defun is-windows ()
  (eq system-type 'windows-nt))
(defun is-linux ()
  (eq system-type 'gnu/linux))

;; フォント設定定数
(defcustom my-font-size 110
  "Default font size for all platforms."
  :type 'integer
  :group 'my-config)

;; フォント候補リスト定数
(defconst windows-font-candidates '("HackGen" "HackGen Console" "MS Gothic" "Consolas"))
(defconst linux-font-candidates '("Noto Sans Mono CJK JP" "Noto Sans" "DejaVu Sans Mono"))

(defcustom my-windows-fonts '("HackGen" "MS Gothic" "Consolas")
  "Windows font priority list (first available will be used)."
  :type '(repeat string)
  :group 'my-config)

(defcustom my-linux-fonts '("Noto Sans Mono CJK JP" "Noto Sans" "DejaVu Sans Mono")
  "Linux font priority list (first available will be used)."
  :type '(repeat string)
  :group 'my-config)

;; ウィンドウサイズ・位置設定定数
(defcustom my-window-top 25
  "Initial window top position."
  :type 'integer
  :group 'my-config)

(defcustom my-window-left 10
  "Initial window left position."
  :type 'integer
  :group 'my-config)

(defcustom my-window-width 60
  "Initial window width in characters."
  :type 'integer
  :group 'my-config)

(defcustom my-window-height 25
  "Initial window height in lines."
  :type 'integer
  :group 'my-config)

;; 編集設定定数
(defcustom my-python-line-length 79
  "Python line length for black formatter."
  :type 'integer
  :group 'my-config)

(defcustom my-fill-column 80
  "Default fill column for text wrapping."
  :type 'integer
  :group 'my-config)

(defcustom my-tab-width 4
  "Default tab width in spaces."
  :type 'integer
  :group 'my-config)

;; 色設定定数
(defcustom my-trailing-whitespace-color "#b14770"
  "Color for highlighting trailing whitespace."
  :type 'string
  :group 'my-config)

(defcustom my-region-background "#a0a8c0"
  "Background color for selected region."
  :type 'string
  :group 'my-config)

(defcustom my-ime-on-cursor-color "green"
  "Cursor color when IME is ON."
  :type 'string
  :group 'my-config)

(defcustom my-ime-off-cursor-color "red"
  "Cursor color when IME is OFF."
  :type 'string
  :group 'my-config)

;; パッケージリポジトリ設定定数
(defcustom my-package-archives '(("melpa" . "https://melpa.org/packages/")
                                ("gnu" . "https://elpa.gnu.org/packages/"))
  "Package archives for Emacs packages."
  :type '(alist :key-type string :value-type string)
  :group 'my-config)

;; --------------------
;; 2. 基本システム設定
;; --------------------

;; 文字エンコーディング設定
(set-language-environment "Japanese")
(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-buffer-file-coding-system 'utf-8)
(setq default-buffer-file-coding-system 'utf-8)

;; ファイル名の文字化け対策(Windows)
(when (is-windows)
  (set-file-name-coding-system 'cp932)
  (setq default-file-name-coding-system 'cp932
        file-name-coding-system 'cp932
        locale-coding-system 'cp932
        default-process-coding-system '(utf-8-unix . cp932)))

;; --------------------
;; 3. 編集・表示設定
;; --------------------

;; 基本編集機能
(electric-pair-mode 1)
(electric-indent-mode -1)
(show-paren-mode 1)
(setq inhibit-startup-screen t
      initial-scratch-message "")
(setq ring-bell-function 'ignore)
(setq shift-select-mode t)

;; インデント・タブ・行設定
(setq-default indent-tabs-mode nil)
(setq-default tab-width my-tab-width)
(setq-default truncate-lines nil)
(setq-default show-trailing-whitespace t)
(set-face-background 'trailing-whitespace my-trailing-whitespace-color)
(setq-default line-spacing 0
              bidi-display-reordering nil)

;; 自動フィル(行折り返し)設定
(add-hook 'prog-mode-hook (lambda () (auto-fill-mode -1)))

;; UI表示設定
(tool-bar-mode -1)
(scroll-bar-mode -1)
(column-number-mode t)
(global-display-line-numbers-mode 1)
(when (display-graphic-p)
  (global-hl-line-mode t))
(setq show-paren-delay 0
      show-paren-style 'parenthesis)

;; スクロール設定
(setq scroll-conservatively 101
      scroll-margin 5
      comint-scroll-show-maximum-output t)

;; キーバインド設定
(fset 'yes-or-no-p 'y-or-n-p)
(global-unset-key "\C-z")
(keyboard-translate ?\C-h ?\C-?)

;; キーバインド設定
(global-set-key (kbd "C-\\") 'toggle-input-method)
(global-set-key [zenkaku-hankaku] 'toggle-input-method)
(global-set-key (kbd "M-SPC") 'toggle-input-method)
(global-set-key (kbd "C-z") 'undo)

;; カーソル色で状態表示
(add-hook 'input-method-activate-hook
          (lambda () (set-cursor-color "red")))
(add-hook 'input-method-inactivate-hook
          (lambda () (set-cursor-color "black")))

;; 使いやすさ設定
(global-auto-revert-mode t)
(when (fboundp 'context-menu-mode)
  (context-menu-mode t))
(when (fboundp 'pixel-scroll-precision-mode)
  (pixel-scroll-precision-mode t))
(setq select-enable-clipboard t)

;; URL自動検出・クリック
(when (fboundp 'goto-address-mode)
  (add-hook 'text-mode-hook 'goto-address-mode)
  (add-hook 'prog-mode-hook 'goto-address-mode))

;; --------------------
;; 4. ファイル・プロジェクト管理
;; --------------------

;; 保存時の設定
(add-hook 'before-save-hook 'delete-trailing-whitespace)

;; 履歴設定
(recentf-mode t)
(setq recentf-max-menu-items 30
      recentf-max-saved-items 1000)

;; Dired設定
(setq dired-listing-switches "-alh")

;; ウィンドウサイズ設定
(setq initial-frame-alist
      (append `((top . ,my-window-top)
                (left . ,my-window-left)
                (width . ,my-window-width)
                (height . ,my-window-height))
              initial-frame-alist))
(setq default-frame-alist initial-frame-alist)

;; --------------------
;; 5. OS別特殊設定
;; --------------------

(cond
 ((is-windows)
  (setq w32-pass-alt-to-system nil
        w32-pass-win-to-system nil)
  (when (file-directory-p "C:/Program Files/Git/bin")
    (add-to-list 'exec-path "C:/Program Files/Git/bin"))

  ;; 文字化け対策(cmdproxy.exe対応)
  (add-hook 'shell-mode-hook
            (lambda ()
              (when (string-match "cmdproxy\\.exe" shell-file-name)
                (set-buffer-process-coding-system 'cp932 'cp932))))

  ;; .lnkファイルサポート(オプション)
  (when (fboundp 'w32-browser)
    (add-to-list 'file-name-handler-alist '("\\.lnk\\'" . w32-browser)))))

;; --------------------
;; 6. 開発環境(パッケージ管理・LSP)
;; --------------------

;; パッケージマネージャー初期化
(require 'package)
(setq package-archives my-package-archives)
(package-initialize)

;; パッケージリストの更新(週1回に制限)
(defun my-update-package-archives-if-needed ()
  "Update package archives if they are outdated (weekly)."
  (let ((last-update-file (expand-file-name "last-package-update" user-emacs-directory)))
    (condition-case nil
        (when (or (not package-archive-contents)
                  (not (file-exists-p last-update-file))
                  (> (- (float-time)
                        (float-time (nth 5 (file-attributes last-update-file))))
                     604800))
          (message "Updating package archives...")
          (package-refresh-contents)
          (with-temp-file last-update-file
            (insert (format-time-string "%Y-%m-%d %H:%M:%S")))
          (message "Package archives updated."))
      (error (message "Package archive update failed - continuing with existing packages")))))

(my-update-package-archives-if-needed)

;; use-packageを最初にインストール
(defun my-ensure-use-package ()
  "Ensure use-package is installed and available."
  (condition-case nil
      (unless (package-installed-p 'use-package)
        (message "Installing use-package...")
        (package-install 'use-package)
        (message "use-package installed successfully."))
    (error (message "use-package installation failed - some features may not work"))))

(my-ensure-use-package)

;; use-packageを有効化(存在する場合のみ)
(when (package-installed-p 'use-package)
  (require 'use-package)
  (setq use-package-always-ensure nil))

;; use-packageが利用できない場合の代替マクロを定義
(unless (package-installed-p 'use-package)
  (defmacro use-package (name &rest args)
    "Fallback macro when use-package is not available"
    `(message "use-package not available - skipping configuration for %s" ',name)))

;; 必須パッケージをインストール
(defvar my-essential-packages
  '(flycheck company projectile markdown-mode magit which-key web-mode emmet-mode tr-ime blacken py-isort)
  "Essential packages for this configuration (excluding eglot - built-in in Emacs 30).")

(defun my-install-essential-packages ()
  "Install essential packages with error handling."
  (dolist (pkg my-essential-packages)
    (condition-case nil
        (unless (package-installed-p pkg)
          (message "Installing %s..." pkg)
          (package-install pkg)
          (message "%s installed successfully." pkg))
      (error (message "Package %s installation failed - continuing without it" pkg)))))

(my-install-essential-packages)

;; 共通開発ツール
(when (package-installed-p 'flycheck)
  (use-package flycheck
    :hook (prog-mode . flycheck-mode)))

(when (package-installed-p 'company)
  (use-package company
    :hook (prog-mode . company-mode)
    :config
    (setq company-idle-delay 0.2)
    (setq company-minimum-prefix-length 2)
    (setq company-selection-wrap-around t)))

(when (package-installed-p 'projectile)
  (use-package projectile
    :init (projectile-mode +1)
    :bind (:map projectile-mode-map
                ("s-p" . projectile-command-map)
                ("C-c p" . projectile-command-map))))

(when (package-installed-p 'which-key)
  (use-package which-key
    :config
    (which-key-mode)))

;; Git操作:Magit
(when (package-installed-p 'magit)
  (use-package magit
    :bind ("C-x g" . magit-status)))

;; Markdown
(when (package-installed-p 'markdown-mode)
  (add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode)))

;; HTML/CSS/JS開発:web-mode
(when (package-installed-p 'web-mode)
  (use-package web-mode
    :mode (("\\.html?\\'" . web-mode)
           ("\\.css\\'"   . web-mode)
           ("\\.jsx?\\'"  . web-mode))
    :config
    (setq web-mode-markup-indent-offset 0)
    (setq web-mode-css-indent-offset 2)
    (setq web-mode-code-indent-offset 2)
    (setq web-mode-enable-auto-pairing t)
    (setq web-mode-enable-css-colorization t)
    (setq web-mode-enable-element-tag-closing nil)))

;; emmet-mode:HTML高速入力
(when (package-installed-p 'emmet-mode)
  (use-package emmet-mode
    :hook (web-mode . emmet-mode)
    :config
    (setq emmet-indentation 0)))

;; --------------------
;; 7. LSP設定(Eglot - Emacs 30標準搭載)
;; --------------------

;; Eglot(Emacs 30で標準搭載)
(when (fboundp 'eglot)
  (message "Using built-in Eglot for LSP support")

  ;; Python用LSP設定
  (add-hook 'python-mode-hook #'eglot-ensure)

  ;; HTML用LSP設定(オプション)
  (add-hook 'html-mode-hook #'eglot-ensure)

  ;; Eglot設定
  (with-eval-after-load 'eglot
    (setq eglot-autoshutdown t)
    (setq eglot-events-buffer-size 0)

    ;; キーバインド(eglotロード後に設定)
    (define-key eglot-mode-map (kbd "C-c l r") #'eglot-rename)
    (define-key eglot-mode-map (kbd "C-c l a") #'eglot-code-actions)
    (define-key eglot-mode-map (kbd "C-c l f") #'eglot-format)))

;; Python整形:Black(PEP8)
(defun my-setup-python-formatting ()
  "Setup Python formatting tools if available."
  (when (executable-find "black")
    (when (package-installed-p 'blacken)
      (use-package blacken
        :hook (python-mode . blacken-mode)
        :config
        (setq blacken-line-length my-python-line-length))))

  ;; isort設定
  (when (and (executable-find "isort") (package-installed-p 'py-isort))
    (use-package py-isort
      :hook (before-save . py-isort-before-save)))

  ;; インストール案内メッセージ
  (unless (executable-find "black")
    (message "Python Black not found. Install with: pip install black"))
  (unless (executable-find "isort")
    (message "Python isort not found. Install with: pip install isort")))

(my-setup-python-formatting)

;; --------------------
;; 8. クロスプラットフォーム対応 日本語入力設定(Emacs 28以降最適化版)
;; --------------------

(cond
 ;; Windows環境設定(Emacs 28以降最適化版)
 ((is-windows)
  ;; tr-imeパッケージの設定(Emacs 28以降はstandard版推奨)
  (defun my-configure-tr-ime ()
    "Configure tr-ime for Windows Japanese input (Emacs 28+ optimized)."
    (when (and (display-graphic-p) (package-installed-p 'tr-ime))
      (condition-case err
          (progn
            (require 'tr-ime)
            ;; Emacs 28以降はstandard版を使用(軽量・安定)
            (tr-ime-standard-install)
            ;; IME設定
            (setq default-input-method "W32-IME")
            (setq w32-ime-mode-line-state-indicator "[あ]")
            (setq w32-ime-mode-line-state-indicator-list '("[--]" "[あ]" "[ア]"))
            (setq w32-ime-composition-window 'point)
            (setq w32-ime-buffer-switch-p nil)
            ;; Emacs 28以降では初期化がより安定
            (w32-ime-initialize)
            (message "tr-ime (standard): Emacs 28+ 初期化完了"))
        (error
         (message "tr-ime configuration failed: %s - continuing with standard Windows IME"
                  (error-message-string err))))))

  (my-configure-tr-ime)

  ;; フォント設定(2024-2025年対応版)
  (let ((selected-font (seq-find (lambda (font) (member font (font-family-list)))
                                 '("HackGen Console NF" "BIZ UDゴシック" "Noto Sans JP" "メイリオ" "MS Gothic"))))
    (if selected-font
        (progn
          (set-face-attribute 'default nil :family selected-font :height my-font-size)
          (cond
           ((string-match "HackGen" selected-font)
            (set-fontset-font nil 'unicode (font-spec :family selected-font))
            (message "Windows フォント: %s(日英混合等幅)" selected-font))
           ((string= selected-font "BIZ UDゴシック")
            (dolist (charset '(japanese-jisx0208 japanese-jisx0212 katakana-jisx0201))
              (set-fontset-font nil charset (font-spec :family selected-font)))
            (message "Windows フォント: %s(UD日本語等幅)" selected-font))
           ((string= selected-font "Noto Sans JP")
            (dolist (charset '(japanese-jisx0208 japanese-jisx0212 katakana-jisx0201))
              (set-fontset-font nil charset (font-spec :family selected-font)))
            (message "Windows フォント: %s(汎用日本語)" selected-font))
           ((string= selected-font "メイリオ")
            (dolist (charset '(japanese-jisx0208 japanese-jisx0212 katakana-jisx0201))
              (set-fontset-font nil charset (font-spec :family selected-font)))
            (message "Windows フォント: %s(標準日本語)" selected-font))
           ((string= selected-font "MS Gothic")
            (dolist (charset '(japanese-jisx0208 japanese-jisx0212 katakana-jisx0201))
              (set-fontset-font nil charset (font-spec :family selected-font)))
            (message "Windows フォント: %s(フォールバック日本語)" selected-font))))
      ;; フォールバック
      (set-face-attribute 'default nil :family "Courier New" :height my-font-size)
      (message "Windows フォント: Courier New(フォールバック)")))

  ;; IMEカーソル色設定
  (add-hook 'input-method-activate-hook (lambda () (set-cursor-color my-ime-on-cursor-color)))
  (add-hook 'input-method-inactivate-hook (lambda () (set-cursor-color my-ime-off-cursor-color)))

  ;; Windows専用のIME制御(Emacs 28以降で安定性向上)
  (when (featurep 'w32-ime)
    (dolist (func '(y-or-n-p yes-or-no-p read-char))
      (w32-ime-wrap-function-to-control-ime func)))

  ;; Emacs 28以降での追加最適化
  (when (>= emacs-major-version 28)
    ;; native-compileの恩恵を受ける
    (setq package-native-compile t)

    ;; tr-imeの最適化オプション(必要に応じて)
    (with-eval-after-load 'tr-ime
      ;; より高速な応答のための設定
      (setq tr-ime-hook-p t)
      ;; IME状態の同期を改善
      (setq tr-ime-sync-p t))))

 ;; Linux/Ubuntu環境設定(2025年対応版)
 ((is-linux)
  ;; 日本語入力・フォント設定(Ubuntu 24.04対応)
  (let ((has-fcitx5 (and (executable-find "fcitx5")
                         (or (getenv "GTK_IM_MODULE")
                             (getenv "QT_IM_MODULE")
                             (getenv "XMODIFIERS")
                             (string-match-p "fcitx5"
                                           (shell-command-to-string "ps aux | grep fcitx5 | grep -v grep || true")))))
        (has-ibus (and (executable-find "ibus")
                       (or (getenv "GTK_IM_MODULE")
                           (getenv "QT_IM_MODULE")
                           (string-match-p "ibus"
                                         (shell-command-to-string "ps aux | grep ibus | grep -v grep || true")))))
        (selected-font (seq-find (lambda (font) (member font (font-family-list)))
                                 linux-font-candidates)))

    ;; Linux環境でmozc.elがインストールされている場合の設定
    (when (and (is-linux) (locate-library "mozc"))
      (require 'mozc)
      (setq default-input-method "japanese-mozc")
      (message "Ubuntu 日本語入力: mozc.el loaded"))

    ;; 日本語入力メソッド設定(2025年版 - fcitx5優先)
    (unless (locate-library "mozc")
      (cond
       (has-fcitx5
        (setq default-input-method "japanese-mozc")
        (message "Ubuntu 日本語入力: fcitx5-mozc detected"))
       (has-ibus
        (setq default-input-method "japanese-mozc")
        (message "Ubuntu 日本語入力: ibus-mozc detected"))
       (t
        (setq default-input-method "japanese")
        (message "Ubuntu 日本語入力: 標準japanese(Mozc未検出)"))))

    ;; フォント設定
    (if selected-font
        (progn
          (set-face-attribute 'default nil :family selected-font :height my-font-size)
          (cond
           ((string= selected-font "Noto Sans Mono CJK JP")
            (set-fontset-font nil 'unicode (font-spec :family selected-font))
            (message "Ubuntu フォント: %s(CJK対応等幅)" selected-font))
           ((string= selected-font "Noto Sans")
            (dolist (charset '(japanese-jisx0208 japanese-jisx0212 katakana-jisx0201))
              (set-fontset-font nil charset (font-spec :family selected-font)))
            (set-fontset-font nil 'unicode (font-spec :family selected-font))
            (message "Ubuntu フォント: %s(汎用フォント)" selected-font))
           ((string= selected-font "DejaVu Sans Mono")
            (let ((japanese-font (seq-find (lambda (font) (member font (font-family-list)))
                                           '("Noto Sans CJK JP" "Noto Sans"))))
              (dolist (charset '(japanese-jisx0208 japanese-jisx0212 katakana-jisx0201))
                (set-fontset-font nil charset (font-spec :family (or japanese-font "DejaVu Sans"))))
              (message "Ubuntu フォント: %s + %s(英文+日本語)"
                       selected-font (or japanese-font "DejaVu Sans"))))))
      ;; フォールバック
      (set-face-attribute 'default nil :family "monospace" :height my-font-size)
      (message "Ubuntu フォント: monospace(フォールバック)")))))

;; 共通設定(全プラットフォーム)

;; フォント関連の最適化
(setq inhibit-compacting-font-caches t)

;; 検索・置換時の日本語入力制御(修正版 - エラーハンドリング強化)

;; isearch開始時に日本語入力を無効化
(add-hook 'isearch-mode-hook
          (lambda ()
            (condition-case err
                (when current-input-method
                  (deactivate-input-method))
              (error
               (message "Failed to deactivate input method in isearch: %s"
                       (error-message-string err))))))

;; replace-string実行前に日本語入力を無効化
(defun my-deactivate-input-method-before-replace (&rest _args)
  "Deactivate input method before replace operations.
Accepts any arguments to work with advice-add.
Handles errors gracefully to prevent operation interruption."
  (condition-case err
      (when current-input-method
        (deactivate-input-method))
    (error
     (message "Failed to deactivate input method before replace: %s"
             (error-message-string err)))))

;; アドバイスの追加(エラーが発生しても処理を継続)
(dolist (func '(replace-string query-replace query-replace-regexp))
  (condition-case err
      (advice-add func :before #'my-deactivate-input-method-before-replace)
    (error
     (message "Failed to add advice to %s: %s"
             func (error-message-string err)))))

;; フォント動的変更の説明
(message "フォント拡大縮小操作: C-x C-+ (拡大) / C-x C-- (縮小) / C-x C-0 (リセット)")

;; --------------------
;; 9. 設定検証・ヘルプ機能
;; --------------------

(defun check-japanese-environment ()
  "日本語環境設定の状況を確認する(2025年版)"
  (interactive)
  (let ((info (list
               (format "プラットフォーム: %s" system-type)
               (format "Emacs: %s" emacs-version)
               (format "フォント: %s" (face-attribute 'default :family))
               (format "入力メソッド: %s" (or default-input-method "未設定")))))

    ;; Windows環境の場合
    (when (is-windows)
      (push (format "tr-ime: %s" (if (featurep 'tr-ime) "読み込み済み" "未読み込み")) info)
      (push (format "w32-ime: %s" (if (featurep 'w32-ime) "読み込み済み" "未読み込み")) info))

    ;; Linux環境の場合
    (when (is-linux)
      (push (format "fcitx5: %s" (if (executable-find "fcitx5") "利用可能" "未インストール")) info)
      (push (format "ibus: %s" (if (executable-find "ibus") "利用可能" "未インストール")) info))

    ;; LSP情報
    (push (format "LSP: %s" (if (fboundp 'eglot) "Eglot (標準搭載)" "未利用可能")) info)
    (push (format "Python LSP: %s" (if (executable-find "pylsp") "python-lsp-server利用可能" "未インストール")) info)

    ;; 結果表示
    (with-output-to-temp-buffer "*Japanese Environment Check*"
      (princ "=== Emacs日本語環境チェック結果 (2025年版) ===\n\n")
      (dolist (msg (reverse info))
        (princ msg)
        (princ "\n"))
      (princ "\n=== 推奨セットアップ ===\n")
      (when (is-windows)
        (princ "Windows: HackGenフォント + tr-ime (MELPA)\n"))
      (when (is-linux)
        (princ "Ubuntu 24.04: sudo apt install fcitx5-mozc fonts-noto-cjk\n"))
      (princ "Python開発: pip install python-lsp-server[all] black isort\n")
      (princ "\n=== 操作方法 ===\n")
      (princ "C-\\ : 日本語入力切替\n")
      (princ "C-x C-+/C-x C-- : フォントサイズ変更\n")
      (princ "C-c l r : LSP変数名変更 (eglot)\n")
      (princ "C-c l a : LSPコードアクション (eglot)\n"))))

(defun my-setup-info ()
  "現在の設定の詳細情報を表示"
  (interactive)
  (with-output-to-temp-buffer "*Setup Information*"
    (princ "=== Emacs設定情報 (2025年修正版) ===\n\n")

    (princ "【基本情報】\n")
    (princ (format "- Emacs version: %s\n" emacs-version))
    (princ (format "- OS: %s\n" system-type))
    (princ (format "- 設定ファイル: %s\n" user-init-file))

    (princ "\n【パッケージ状況】\n")
    (dolist (pkg '(use-package eglot flycheck company projectile markdown-mode magit which-key web-mode emmet-mode tr-ime))
      (princ (format "- %s: %s\n"
                     pkg
                     (cond
                      ((eq pkg 'eglot) (if (fboundp 'eglot) "標準搭載" "未利用可能"))
                      ((package-installed-p pkg) "インストール済み")
                      (t "未インストール")))))

    (princ "\n【外部ツール】\n")
    (dolist (tool '("pylsp" "black" "isort" "git"))
      (princ (format "- %s: %s\n"
                     tool
                     (if (executable-find tool) "利用可能" "未検出"))))))

;; --------------------
;; 10. 起動完了処理
;; --------------------

;; 起動完了メッセージ
(add-hook 'after-init-hook
          (lambda ()
            (let ((lsp-status (if (fboundp 'eglot) "Eglot(標準)" "未利用可能"))
                  (ime-status (cond
                               ((and (is-windows) (featurep 'tr-ime)) "tr-ime")
                               ((and (is-linux) (executable-find "fcitx5")) "fcitx5-mozc")
                               ((and (is-linux) (executable-find "ibus")) "ibus-mozc")
                               (t "標準"))))
              (message "Emacs初期化完了 - %s環境 (Emacs %d.%d) | LSP: %s | 日本語: %s"
                       (cond ((is-windows) "Windows")
                             ((is-linux) "Ubuntu/Linux")
                             (t "その他"))
                       emacs-major-version
                       emacs-minor-version
                       lsp-status
                       ime-status))))

;; 終了メッセージ
(message "Emacs設定読み込み完了 - 2025年修正版 (PEP8 + 多言語対応 + クロスプラットフォーム + Eglot + IME制御改善)")

;;; init.el ends here

Emacsの基本編集機能のガイド

概要

Emacsの操作コマンドを覚えることは、効率的な編集作業を行う上で重要である。Emacsでは、カーソル移動(C-p/n/f/b)、テキスト編集(C-k/y)、ファイル操作(C-x C-f/s)、検索(C-s)、バッファ管理(C-x C-b)、ウィンドウ分割(C-x 2/1)、リージョン指定(C-Space)などの基本機能が用意されている。

1. 基本的なカーソル操作とテキスト編集

Emacsを使って効率的にテキストを編集するためには、カーソルの操作をマスターすることが重要である。

カーソル移動

Emacsでは、以下のキーバインドでカーソルを移動できる。

テキスト削除

Emacsでは、C-kコマンドでテキストを削除できる。

貼り付け

削除したテキストは、キルリングに保存される。

マーク設定

テキストの範囲を選択する際には、マークを使用する。

元に戻す(アンドゥ)

誤った操作を取り消すには、アンドゥ機能を使用する。

2. ファイル操作

ファイルの読み込みや保存はEmacsの重要な機能である。

ファイルを開く

ファイルを保存

3. 検索・置換

Emacsの検索機能により、効率的な編集が可能である。

インクリメンタル検索

文字列置換

4. バッファ管理

Emacsは複数のバッファを同時に管理でき、以下のような操作が可能である。

バッファ一覧

バッファ切り替え

バッファ削除

5. ウィンドウ操作

Emacsでは画面を分割して複数のバッファを同時に表示できる。

ウィンドウ分割

他のウィンドウを閉じる

他のウィンドウに移動

6. リージョン指定とマーク設定

Emacsでは、テキストの一部を選択するためにリージョンという概念を使用する。リージョンを指定する手順は以下のとおりである。

指定したい領域の一方の隅に目印をつけ、もう一方の隅にカーソルを移動させる。目印をつけた場所とカーソルとの間が領域(リージョン)となる。Emacsでは目印をマークと呼び、目印を設定することをマークすると呼ぶ。カーソルをマークする場所まで移動し、C-Spaceとタイプすることでマークが設定され、ミニバッファに「Mark set」と表示される。

カーソル位置の文字すべてが領域として指定されるわけではなく、カーソルの四角形の左辺を基準として領域が指定される。この基準をポイントと呼び、リージョンはマークしたときのポイントから現在のカーソルのポイントまでとなる。

7. テキスト削除

Emacsにはdeleteとkillという2つのコマンドがある。deleteは文字を消去するのみであるが、killは切り取りの意味合いがある。killで取り除いたテキストはキルリングという領域に保存される。キルリングに保存されたテキストは、別のコマンドで取り出すことができるが、deleteで消去されたテキストはundoを使わない限り復元できない。

領域の削除

リージョンが指定された状態でC-wをタイプすると、指定された領域が削除される。C-wは指定領域を削除するコマンド(kill-region)である。

8. 複写

領域をバッファから削除せずにキルリングへ格納するにはM-w(kill-ring-save)を使用する。このコマンドもマークとカーソルで領域を指定する。また、マウスの左ボタンドラッグでも複写できる。ドラッグした範囲の色が変わる。

9. 貼り付け

キルリングに取り込まれたテキストを取り出すにはヤンク(yank)を使用する。ヤンクコマンドはC-yに割り当てられている。C-yをタイプするとキルリングに格納されているテキストをカーソル位置に挿入する。

さらに、その前にキルリングに記憶されたテキストも順次取り出すことができる。古い削除テキストを取り出すには、C-yコマンドの直後にM-y(yank-pop)をタイプする。M-yを押すたびに、取り出されるテキストが順々に古い削除テキストに入れ替わる。

また、マウスの中ボタンクリックでマウスカーソルがある位置にテキストを挿入することも可能である。

10. 取り消し

操作を誤った場合など、以前の状態に戻すにはアンドゥ(操作の取り消し)機能を使用する。C-/を入力すると、直前の操作を取り消すことができる。アンドゥは複数回実行できるが、回数には制限がある。

11. 編集モード

メジャーモード

メジャーモードは主モードとも呼ばれ、プログラミング言語の編集や特定の種類の文章操作に関する知識を提供する。専用のコマンドとキー設定、入力の補助を提供する。

例えば、C言語編集用のメジャーモード「c-mode」はC言語スタイルのインデントを自動で行う。メジャーモードは各バッファに一つだけ設定でき、複数のメジャーモードを設定することはできない。

メジャーモードには、以下のようなものがある(一部を抜粋)。

モードのロード

新しいバッファは特に何も指定しなければ、fundamental-modeになる。メジャーモードを設定するには、そのモードをロードする。モードのロードはM-xで、コマンドを直接実行する。例えば、Cモードを設定するには、M-x c-modeとタイプする。

新しいバッファを作成したりファイルを読み込んだときは、バッファ名の拡張子から自動的に適切なメジャーモードをロードする。この設定は.emacsに記述できる。

(setq auto-mode-alist (append '(("\\.C$" . c++-mode) ("\\.cc$" . c++-mode) ("\\.c$" . c-mode) ("\\.h$" . c++-mode) ) auto-mode-alist))

マイナーモード

マイナーモードはメジャーモードに対して、各種の機能を付加する。これらのモードは常に設定されているというわけではない。マイナーモードを設定するにはM-xを使って直接マイナーモードの関数を呼び出す。上書きモードを設定するときは、M-x overwrite-modeとタイプする。モードが設定されている場合は解除され、設定されていない場合は設定される。マイナーモードはメジャーモードと異なり、一つのバッファに複数設定できる。

マイナーモードには、以下のようなものがある(一部を抜粋)。

設定後の確認方法

設定の動作確認

設定が正しく動作しているかを確認するため、以下の手順を実行する。

詳細確認コマンド

より詳細な確認を行う場合は、以下のコマンドを使用する。

トラブルシューティング

よくある問題と解決方法

Emacsの設定や使用中に問題が発生した場合は、以下の解決方法を試す。