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

【概要】Emacsはプログラミングや文書作成に適したテキストエディタである。WindowsではwingetでEmacsをインストールでき、Ubuntuではaptでインストールできる。本ガイドでは、Emacsのインストール手順に加え、オプションとしてフォントやPythonのインストールも紹介している。さらに、Emacsの設定ファイルinit.elとして、Python、HTML、CSS、テキストファイル編集用の機能を設定したサンプルも示している。このサンプルには、LSP(Language Server Protocol:コード補完や定義ジャンプなどの機能を提供する仕組み)による開発支援機能も含まれている。全機能を使用するには、追加でblack、isort、python-lsp-serverのインストールが必要であり、その手順も示している。基本編集操作、メジャーモード、マイナーモード、トラブルシューティングの説明も行っている。

Emacsの画面例

【前提条件】本ガイドは、コマンドライン操作の基本的な知識があることを前提としている。Pythonの開発環境構築はオプションであり、Emacsをテキストエディタとして使用するだけであれば、Emacsのインストールのみで利用可能である。

【目次】

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

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)が可能である。

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

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

Emacsの基本概念

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

コマンド実行環境の準備

本ガイドでは、コマンドラインからソフトウェアのインストールや設定を行う。OSごとにコマンド実行環境の起動方法が異なるため、以下の手順に従って準備する。

Windows環境

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

Ubuntu環境

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

Windows環境での設定

Emacsインストールコマンド

winget(Windowsのパッケージマネージャー)を使用してEmacsをインストールする。管理者権限でコマンドプロンプトを起動し、以下を実行する。

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のインストールコマンド(オプション)

PythonでのプログラミングにEmacsを使用する場合、Pythonをインストールする。インストール済みの場合は実行不要である。

Windowsで、コマンドプロンプト管理者権限で起動する(手順:Windowsキーまたはスタートメニューを押し、「cmd」と入力し、右クリックメニューなどで「管理者として実行」を選択する)。

REM Python 3.12 をシステム領域にインストール
winget install --scope machine --id Python.Python.3.12 -e --silent --accept-source-agreements --accept-package-agreements

REM パス長制限の解除(Windowsの260文字パス制限を解除し、長いパスを扱えるようにする)
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled /t REG_DWORD /d 1 /f
reg query "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled

REM Python のパス設定
set "PYTHON_PATH=C:\Program Files\Python312"
set "PYTHON_SCRIPTS_PATH=C:\Program Files\Python312\Scripts"
if exist "%PYTHON_PATH%" setx PYTHON_PATH "%PYTHON_PATH%" /M >nul
if exist "%PYTHON_SCRIPTS_PATH%" setx PYTHON_SCRIPTS_PATH "%PYTHON_SCRIPTS_PATH%" /M >nul
for /f "skip=2 tokens=2*" %a in ('reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v Path') do set "SYSTEM_PATH=%b"
echo "%SYSTEM_PATH%" | find /i "%PYTHON_PATH%" >nul
if errorlevel 1 setx PATH "%PYTHON_PATH%;%PYTHON_SCRIPTS_PATH%;%SYSTEM_PATH%" /M >nul

Python開発環境のセットアップ(オプション)

以下のツールをインストールすることで、Emacsでのpython開発が効率化される。pip(Pythonのパッケージマネージャー)を使用してインストールする。

管理者権限でコマンドプロンプトを起動し、以下を実行する。

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

DPIスケーリング無効化の設定(オプション)

高DPIディスプレイ環境でEmacsの表示がぼやける場合、DPIスケーリングを無効化することで表示が鮮明になる。管理者権限でコマンドプロンプトを起動し、以下を実行する。

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

フォント設定(オプション)

プログラミング用フォント「HackGen」をインストールする。HackGenは日本語と英語の文字幅が調整されており、コードの視認性が向上する。管理者権限でコマンドプロンプトを起動し、以下を実行する。

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のインストールコマンド

apt(Ubuntuのパッケージマネージャー)を使用してEmacsとPythonをインストールする。ターミナルを開き、以下を実行する。

# システムの更新
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

# Git のインストール
sudo apt git

# 日本語入力のためのインストールと設定
sudo apt install fcitx5-mozc fonts-noto-cjk emacs-mozc
im-config -n fcitx5

# 設定ファイル作成
mkdir -p ~/.config/fcitx5
cat > ~/.config/fcitx5/profile << 'EOF'
[Groups/0]
Name=Default
Default Layout=jp
DefaultIM=mozc

[Groups/0/Items/0]
Name=keyboard-jp

[Groups/0/Items/1]
Name=mozc

[GroupOrder]
0=Default
EOF

設定が終わったら再ログインする

フォント設定(オプション)

プログラミング用フォント「HackGen」をインストールする。HackGenは日本語と英語の文字幅が調整されており、コードの視認性が向上する。ターミナルを開き、以下を実行する。

# 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開発環境のセットアップ(オプション)

以下のツールをインストールすることで、EmacsでのPython開発が効率化される。

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

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

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

init.elはEmacsの設定ファイルである。このファイルを編集することで、Emacsの動作をカスタマイズできる。保存場所はOSによって異なる。

以下に、Python、HTML、CSS、テキストファイル編集に対応したinit.elのサンプルを示す。このサンプルには以下の機能が含まれている。

注意:Python開発支援機能を使用するには、事前にblack、isort、python-lsp-serverのインストールが必要である。

;;; 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修正)
;; - Linux日本語入力設定の修正(fcitx5/ibus/mozc.el対応)

;;; Code:

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

;; OS判別関数
(defun is-windows ()
  "Return t if running on Windows."
  (eq system-type 'windows-nt))

(defun is-linux ()
  "Return t if running on 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")
  "Font candidates for Windows.")

(defconst linux-font-candidates '("Noto Sans Mono CJK JP" "Noto Sans" "DejaVu Sans Mono")
  "Font candidates for Linux.")

(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)

(unless (display-graphic-p)
  (xterm-mouse-mode -1)
  (menu-bar-mode -1))

;; スクロール設定
(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
    (setq web-mode-enable-css-colorization t)
    (setq web-mode-enable-element-tag-closing nil)(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. クロスプラットフォーム対応 日本語入力設定(2025年修正版)
;; --------------------

(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)
  (let ((has-mozc-el (locate-library "mozc"))
        (has-fcitx5 (executable-find "fcitx5"))
        (has-ibus (executable-find "ibus"))
        (selected-font (seq-find (lambda (font) (member font (font-family-list)))
                                 linux-font-candidates)))

    ;; 日本語入力メソッド設定
    (cond
     ;; mozc.elがインストールされている場合(Emacs内蔵Mozc)
     (has-mozc-el
      (require 'mozc)
      (setq default-input-method "japanese-mozc")
      (message "Linux 日本語入力: mozc.el(Emacs内蔵Mozc)"))

     ;; fcitx5がある場合(システムIME - Emacs側設定不要)
     (has-fcitx5
      (message "Linux 日本語入力: fcitx5(システムIME)"))

     ;; ibusがある場合(システムIME - Emacs側設定不要)
     (has-ibus
      (message "Linux 日本語入力: ibus(システムIME)"))

     ;; フォールバック
     (t
      (message "Linux 日本語入力: 未検出(fcitx5-mozcまたはemacs-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 "Linux フォント: %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 "Linux フォント: %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 "Linux フォント: %s + %s(英文+日本語)"
                       selected-font (or japanese-font "DejaVu Sans"))))))
      ;; フォールバック
      (set-face-attribute 'default nil :family "monospace" :height my-font-size)
      (message "Linux フォント: 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 "未設定(システムIME使用)")))))

    ;; 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 "mozc.el: %s" (if (locate-library "mozc") "利用可能" "未インストール")) info)
      (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:\n")
        (princ "  システムIME: sudo apt install fcitx5-mozc\n")
        (princ "  Emacs内蔵:   sudo apt install emacs-mozc\n")
        (princ "  フォント:    sudo apt install fonts-noto-cjk\n"))
      (princ "Python開発: pip install python-lsp-server[all] black isort\n")
      (princ "\n=== 操作方法 ===\n")
      (princ "C-\\ : 日本語入力切替(mozc.el使用時のみ)\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) "利用可能" "未検出"))))

    (princ "\n【日本語入力】\n")
    (princ (format "- default-input-method: %s\n" (or default-input-method "未設定")))
    (when (is-linux)
      (princ (format "- mozc.el: %s\n" (if (locate-library "mozc") "あり" "なし")))
      (princ (format "- fcitx5: %s\n" (if (executable-find "fcitx5") "あり" "なし")))
      (princ (format "- ibus: %s\n" (if (executable-find "ibus") "あり" "なし"))))))

;; --------------------
;; 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) (locate-library "mozc")) "mozc.el")
                               ((and (is-linux) (executable-find "fcitx5")) "fcitx5(システム)")
                               ((and (is-linux) (executable-find "ibus")) "ibus(システム)")
                               (t "標準"))))
              (message "Emacs初期化完了 - %s環境 (Emacs %d.%d) | LSP: %s | 日本語: %s"
                       (cond ((is-windows) "Windows")
                             ((is-linux) "Linux")
                             (t "その他"))
                       emacs-major-version
                       emacs-minor-version
                       lsp-status
                       ime-status))))

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

;;; init.el ends here

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

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

カーソル移動

テキスト削除と貼り付け

ファイル操作

検索・置換

バッファ管理

ウィンドウ操作

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

Emacsでは、テキストの一部を選択するためにリージョンという概念を使用する。指定したい領域の一方の端に目印をつけ、もう一方の端にカーソルを移動させる。目印をつけた場所とカーソルとの間が領域(リージョン)となる。

カーソルをマークする場所まで移動し、C-Spaceとタイプすることでマークが設定され、ミニバッファに「Mark set」と表示される。カーソル位置の文字がすべて領域として指定されるわけではなく、カーソルの四角形の左辺を基準として領域が指定される。この基準をポイントと呼ぶ。

テキスト削除と複写

Emacsにはdeleteとkillという2種類のコマンドがある。deleteは文字を消去するのみであるが、killは切り取りの機能を持つ。killで取り除いたテキストはキルリングに保存される。

編集モード

メジャーモード

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

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

メジャーモードには、以下のようなものがある。

モードのロード

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

新しいバッファを作成したりファイルを読み込んだりしたときは、バッファ名の拡張子から自動的に適切なメジャーモードがロードされる。

マイナーモード

マイナーモードはメジャーモードに対して各種の機能を付加する。マイナーモードを設定するにはM-xを使って直接マイナーモードの関数を呼び出す。マイナーモードはメジャーモードと異なり、一つのバッファに複数設定できる。

マイナーモードには、以下のようなものがある。

設定後の確認方法

設定の動作確認

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

詳細確認コマンド

トラブルシューティング

問題と解決方法