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では、カーソル移動(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)が可能である。
【目次】
Emacsの基本の要点
キーバインド表記について
Emacsでは、以下の表記方法を用いてキーバインドを示す。
- C-:Ctrlキーを表す(例:C-pはCtrl+p)
 - M-:Altキーを表す(例:M-xはAlt+x)
 - M-x:Alt+xキーでコマンド実行(例:M-x package-list-packages)
 
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]
init.el設定(Windows・Linux対応)
次のファイルを編集する。
- Windows: C:\Users\[ユーザー名]\AppData\Roaming\.emacs.d\init.el
 - Ubuntu: ~/.emacs.d/init.el
 
;;; 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優先)
    ;; mozc.elが利用可能でない場合のみ設定
    (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設定読み込み完了(PEP8 + 多言語対応 + クロスプラットフォーム + Eglot + IME制御改善)")
;;; init.el ends here
(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(package-selected-packages
   '(magit markdown-mode cmake-mode which-key web-mode use-package tr-ime py-isort projectile flycheck emmet-mode company blacken)))
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 )
Emacsの基本編集機能のガイド
基本的なカーソル操作とテキスト編集
カーソル移動
- C-p / C-n:カーソルを前の行/次の行に移動する
 - C-f / C-b:カーソルを一文字前方/後方に移動させる
 - 矢印キーも同様にカーソル移動に使用できる
 
テキスト削除と貼り付け
- C-k:カーソル位置から行末までを削除する
 - C-y:キルリングから最新のテキストをカーソル位置に挿入する
 - C-Space:現在のカーソル位置にマークを設定する
 - C-/:直前の操作を取り消す
 
ファイル操作
- C-x C-f:ファイルを開く
 - C-x C-s:現在のバッファを保存する
 
検索・置換
- C-s:インクリメンタル検索を開始する
 - M-x replace-string:指定した文字列を他の文字列に一括置換する
 
バッファ管理
- C-x C-b:現在開いているバッファの一覧を表示する
 - M-x switch-to-buffer:別のバッファに切り替える
 - M-x kill-buffer:バッファを削除する
 
ウィンドウ操作
- C-x 2:現在のバッファを新しいウィンドウに表示して分割する
 - C-x 1:他のすべてのウィンドウを閉じる
 - C-x o:他のウィンドウにカーソルを移動する
 
リージョン指定とマーク設定
Emacsでは、テキストの一部を選択するためにリージョンという概念を使用する。指定したい領域の一方の隅に目印をつけ、もう一方の隅にカーソルを移動させる。目印をつけた場所とカーソルとの間が領域(リージョン)となる。
カーソルをマークする場所まで移動し、C-Spaceとタイプすることでマークが設定され、ミニバッファに「Mark set」と表示される。カーソル位置の文字すべてが領域として指定されるわけではなく、カーソルの四角形の左辺を基準として領域が指定される。この基準をポイントと呼ぶ。
テキスト削除と複写
Emacsにはdeleteとkillという2つのコマンドがある。deleteは文字を消去するのみであるが、killは切り取りの意味合いがある。killで取り除いたテキストはキルリングという領域に保存される。
- C-w:指定された領域を削除する(kill-region)
 - M-w:領域をバッファから削除せずにキルリングへ格納する(kill-ring-save)
 - C-y:キルリングに格納されているテキストをカーソル位置に挿入する
 - M-y:C-yコマンドの直後にタイプすると、古い削除テキストを順次取り出す
 
編集モード
メジャーモード
メジャーモードは主モードとも呼ばれ、プログラミング言語の編集や特定の種類の文章操作に関する知識を提供する。専用のコマンドとキー設定、入力の補助を提供する。
例えば、C言語編集用のメジャーモード「c-mode」はC言語スタイルのインデントを自動で行う。メジャーモードは各バッファに一つだけ設定でき、複数のメジャーモードを設定することはできない。
メジャーモードには、以下のようなものがある。
- fundamental-mode:特に機能を持たないモード
 - text-mode:通常の文章を編集するためのモード
 - c-mode、c++-mode:C言語およびC++言語のプログラムソースコード編集に適したモード
 
モードのロード
新しいバッファは特に何も指定しなければ、fundamental-modeになる。メジャーモードを設定するには、そのモードをロードする。モードのロードはM-xで、コマンドを直接実行する。例えば、Cモードを設定するには、M-x c-modeとタイプする。
新しいバッファを作成したりファイルを読み込んだときは、バッファ名の拡張子から自動的に適切なメジャーモードをロードする。
マイナーモード
マイナーモードはメジャーモードに対して、各種の機能を付加する。マイナーモードを設定するにはM-xを使って直接マイナーモードの関数を呼び出す。マイナーモードはメジャーモードと異なり、一つのバッファに複数設定できる。
マイナーモードには、以下のようなものがある。
- overwrite-mode:入力された文字は挿入されず上書きされる
 - auto-fill-mode:自動的に文章を一定の位置で改行する
 - line-number-mode:モードラインに現在の行を表示する
 
設定後の確認方法
設定の動作確認
設定が正しく動作しているかを確認するため、以下の手順を実行する。
- フォント設定:Emacsで新規ファイルを開き、「あいうえお」と入力してフォント表示を確認する
 - LSP機能:.pyファイルを開き、変数名を途中まで入力してTabキーで補完候補表示を確認する
 - Python開発環境:Pythonファイル保存時にBlackによる自動整形を確認する
 - 日本語入力(Windows):C-\でIME切り替えができることを確認する
 
詳細確認コマンド
- M-x describe-font:現在のフォント設定を表示
 - M-x package-list-packages:全パッケージの状態を確認
 
トラブルシューティング
よくある問題と解決方法
- パッケージインストール失敗:M-x package-refresh-contentsを実行してパッケージリストを更新する
 - フォント表示問題:フォントが正しくインストールされているか確認し、Emacsを再起動する
 - LSPサーバー接続エラー:pip install python-lsp-server[all]を実行する
 - Python環境問題:pip install black isortを実行する
 - Windows日本語入力問題:Emacsを管理者権限で起動して設定を確認する