GNU Emacs
Development Tool
GNU Emacs
Overview
GNU Emacs is a highly extensible text editor developed by Richard Stallman. Called an "operating system" due to its rich feature set, it is beloved by many programmers for its infinite extensibility through Emacs Lisp.
Details
Emacs development began in 1976 by Richard Stallman and was released as GNU Emacs in 1985. Beyond a simple text editor, it functions as a platform integrating all kinds of features including email, web browsing, calendar, games, and programming environments.
Emacs' greatest feature is complete programmability through Emacs Lisp. Nearly all editor functions are written in Emacs Lisp, and users can freely add or modify features. Powerful packages exist including org-mode (information organization), Magit (Git client), mu4e (email client), and evil-mode (Vim emulation).
The self-documenting design allows access to documentation for all functions within the editor, enabling function definition reference and dynamic feature exploration. It provides advanced text editing features including buffer-based window system, powerful keybinding system, regular expression search and replace, and diverse programming language support.
Advantages and Disadvantages
Advantages
- Infinite Extensibility: Complete customization capability through Emacs Lisp
- Integrated Platform: Integration of editor, email, browser, and PIM functions
- Self-Documenting: Complete documentation reference within the editor
- Powerful Packages: High-functionality packages like Org-mode, Magit, mu4e
- Programmable: All operations can be automated through programming
- Long History: Stability and maturity cultivated through 40+ years of development
- Independence: Complete environment independent of other tools
Disadvantages
- Steep Learning Curve: Long-term commitment required to learn unique operation system
- Heavy Resource Consumption: High memory and CPU usage due to many features
- Terminal Limitations: Feature restrictions in terminal version compared to GUI
- Complex Initial Setup: Significant configuration work required even for basic use
- Outdated UI: Interface appears dated compared to modern editors
- Plugin Management: Plugin conflicts and compatibility issues
- Startup Time: Slow startup due to loading extensive configuration
Key Links
Code Examples
Basic Configuration (init.el)
;; ~/.emacs.d/init.el - Basic Configuration
;; Package system setup
(require 'package)
(setq package-enable-at-startup nil)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
(add-to-list 'package-archives '("gnu" . "https://elpa.gnu.org/packages/"))
(package-initialize)
;; Install use-package
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))
(eval-when-compile
(require 'use-package))
;; Basic settings
(setq inhibit-startup-message t) ; Hide startup message
(setq inhibit-scratch-message nil) ; Scratch buffer message
(setq initial-scratch-message "") ; Empty initial message
;; UI settings
(menu-bar-mode -1) ; Hide menu bar
(tool-bar-mode -1) ; Hide tool bar
(scroll-bar-mode -1) ; Hide scroll bar
(global-display-line-numbers-mode 1) ; Show line numbers
(column-number-mode 1) ; Show column number
(show-paren-mode 1) ; Highlight matching parentheses
(global-hl-line-mode 1) ; Highlight cursor line
;; Indentation settings
(setq-default indent-tabs-mode nil) ; Convert tabs to spaces
(setq-default tab-width 4) ; Tab width
(setq indent-line-function 'insert-tab) ; Indent function
;; Backup and auto-save
(setq backup-directory-alist `((".*" . ,temporary-file-directory)))
(setq auto-save-file-name-transforms `((".*" ,temporary-file-directory t)))
(setq backup-by-copying t)
(setq delete-old-versions t)
(setq kept-new-versions 6)
(setq kept-old-versions 2)
(setq version-control t)
;; Encoding
(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)
;; Key bindings
(global-set-key (kbd "C-h") 'delete-backward-char)
(global-set-key (kbd "M-?") 'help-command)
(global-set-key (kbd "C-c l") 'toggle-truncate-lines)
(global-set-key (kbd "C-c r") 'replace-string)
(global-set-key (kbd "C-c R") 'replace-regexp)
(global-set-key (kbd "C-x C-b") 'ibuffer)
;; Font settings
(when (eq system-type 'darwin)
(set-face-attribute 'default nil :family "Monaco" :height 140))
(when (eq system-type 'gnu/linux)
(set-face-attribute 'default nil :family "DejaVu Sans Mono" :height 110))
(when (eq system-type 'windows-nt)
(set-face-attribute 'default nil :family "Consolas" :height 110))
Package Configuration (use-package)
;; Theme settings
(use-package doom-themes
:ensure t
:config
(setq doom-themes-enable-bold t
doom-themes-enable-italic t)
(load-theme 'doom-one t)
(doom-themes-visual-bell-config)
(doom-themes-org-config))
;; Completion framework
(use-package ivy
:ensure t
:init
(ivy-mode 1)
:config
(setq ivy-use-virtual-buffers t)
(setq enable-recursive-minibuffers t)
(global-set-key (kbd "C-s") 'swiper)
(global-set-key (kbd "M-x") 'counsel-M-x)
(global-set-key (kbd "C-x C-f") 'counsel-find-file))
(use-package counsel
:ensure t
:after ivy)
(use-package swiper
:ensure t
:after ivy)
;; Project management
(use-package projectile
:ensure t
:init
(projectile-mode +1)
:bind (:map projectile-mode-map
("s-p" . projectile-command-map)
("C-c p" . projectile-command-map)))
;; Git integration
(use-package magit
:ensure t
:bind (("C-x g" . magit-status)
("C-x M-g" . magit-dispatch)))
;; Company completion
(use-package company
:ensure t
:init
(global-company-mode)
:config
(setq company-idle-delay 0.2)
(setq company-minimum-prefix-length 1)
(setq company-selection-wrap-around t))
;; File tree
(use-package neotree
:ensure t
:config
(global-set-key [f8] 'neotree-toggle)
(setq neo-theme 'arrow))
;; Org-mode enhancement
(use-package org
:ensure t
:config
(setq org-directory "~/org/")
(setq org-default-notes-file (concat org-directory "notes.org"))
(setq org-agenda-files (list org-directory))
(global-set-key (kbd "C-c a") 'org-agenda)
(global-set-key (kbd "C-c c") 'org-capture)
(global-set-key (kbd "C-c l") 'org-store-link))
;; Evil mode (Vim emulation)
(use-package evil
:ensure t
:init
(setq evil-want-integration t)
(setq evil-want-keybinding nil)
:config
(evil-mode 1))
(use-package evil-collection
:after evil
:ensure t
:config
(evil-collection-init))
;; LSP
(use-package lsp-mode
:ensure t
:init
(setq lsp-keymap-prefix "C-c l")
:hook ((python-mode . lsp)
(javascript-mode . lsp)
(lsp-mode . lsp-enable-which-key-integration))
:commands lsp)
(use-package lsp-ui
:ensure t
:commands lsp-ui-mode)
(use-package lsp-ivy
:ensure t
:commands lsp-ivy-workspace-symbol)
Org-mode Configuration Example
;; Detailed Org-mode configuration
(use-package org
:ensure t
:config
;; Basic settings
(setq org-directory "~/org/")
(setq org-default-notes-file (concat org-directory "inbox.org"))
(setq org-agenda-files (list (concat org-directory "gtd.org")
(concat org-directory "projects.org")
(concat org-directory "calendar.org")))
;; TODO keywords
(setq org-todo-keywords
'((sequence "TODO(t)" "NEXT(n)" "WAITING(w)" "|" "DONE(d)" "CANCELLED(c)")))
;; Tags
(setq org-tag-alist '(("@work" . ?w)
("@home" . ?h)
("@computer" . ?c)
("@phone" . ?p)
("@errands" . ?e)))
;; Capture templates
(setq org-capture-templates
'(("t" "Todo" entry (file+headline org-default-notes-file "Tasks")
"* TODO %?\n %i\n %a")
("j" "Journal" entry (file+datetree "~/org/journal.org")
"* %?\nEntered on %U\n %i\n %a")
("m" "Meeting" entry (file+headline "~/org/meetings.org" "Meetings")
"* %? :meeting:\n %U\n %i")
("n" "Note" entry (file+headline "~/org/notes.org" "Notes")
"* %?\n %U\n %i")))
;; Agenda settings
(setq org-agenda-custom-commands
'(("d" "Daily agenda and all TODOs"
((agenda "" ((org-agenda-span 1)))
(alltodo "" ((org-agenda-overriding-header "All TODOs")))))))
;; Babel settings (code execution)
(org-babel-do-load-languages
'org-babel-load-languages
'((python . t)
(shell . t)
(emacs-lisp . t)
(javascript . t)))
;; Key bindings
(global-set-key (kbd "C-c a") 'org-agenda)
(global-set-key (kbd "C-c c") 'org-capture)
(global-set-key (kbd "C-c l") 'org-store-link))
Custom Function Examples
;; Custom function definitions
;; Function to duplicate current line
(defun duplicate-line ()
"Duplicate the current line."
(interactive)
(let ((line (buffer-substring-no-properties
(line-beginning-position)
(line-end-position))))
(end-of-line)
(newline)
(insert line)))
;; Function to delete trailing whitespace and save
(defun delete-trailing-whitespace-and-save ()
"Delete trailing whitespace and save the file."
(interactive)
(delete-trailing-whitespace)
(save-buffer))
;; Window splitting functions
(defun split-window-below-and-switch ()
"Split window below and switch to it."
(interactive)
(split-window-below)
(balance-windows)
(other-window 1))
(defun split-window-right-and-switch ()
"Split window right and switch to it."
(interactive)
(split-window-right)
(balance-windows)
(other-window 1))
;; Function to open init file
(defun open-init-file ()
"Open the init file."
(interactive)
(find-file user-init-file))
;; Function to reload init file
(defun reload-init-file ()
"Reload the init file."
(interactive)
(load-file user-init-file))
;; Key binding settings
(global-set-key (kbd "C-c d") 'duplicate-line)
(global-set-key (kbd "C-c s") 'delete-trailing-whitespace-and-save)
(global-set-key (kbd "C-x 2") 'split-window-below-and-switch)
(global-set-key (kbd "C-x 3") 'split-window-right-and-switch)
(global-set-key (kbd "C-c i") 'open-init-file)
(global-set-key (kbd "C-c r") 'reload-init-file)
;; Buffer management functions
(defun kill-other-buffers ()
"Kill all buffers except the current one."
(interactive)
(mapc 'kill-buffer
(delq (current-buffer)
(remove-if-not 'buffer-file-name (buffer-list)))))
(defun switch-to-previous-buffer ()
"Switch to the previous buffer."
(interactive)
(switch-to-buffer (other-buffer (current-buffer) 1)))
(global-set-key (kbd "C-c k") 'kill-other-buffers)
(global-set-key (kbd "C-c b") 'switch-to-previous-buffer)
Programming Environment Configuration
;; Programming language settings
;; Python configuration
(use-package python-mode
:ensure t
:mode "\\.py\\'"
:hook (python-mode . lsp-deferred)
:config
(setq python-indent-offset 4))
;; JavaScript/TypeScript configuration
(use-package js2-mode
:ensure t
:mode "\\.js\\'"
:hook (js2-mode . lsp-deferred)
:config
(setq js2-basic-offset 2))
(use-package typescript-mode
:ensure t
:mode "\\.ts\\'"
:hook (typescript-mode . lsp-deferred)
:config
(setq typescript-indent-level 2))
;; Web development
(use-package web-mode
:ensure t
:mode (("\\.html?\\'" . web-mode)
("\\.css\\'" . web-mode)
("\\.jsx?\\'" . web-mode)
("\\.tsx?\\'" . web-mode))
:config
(setq web-mode-markup-indent-offset 2)
(setq web-mode-css-indent-offset 2)
(setq web-mode-code-indent-offset 2))
;; Markdown
(use-package markdown-mode
:ensure t
:mode (("\\.md\\'" . markdown-mode)
("\\.markdown\\'" . markdown-mode))
:config
(setq markdown-command "multimarkdown"))
;; YAML
(use-package yaml-mode
:ensure t
:mode "\\.ya?ml\\'")
;; JSON
(use-package json-mode
:ensure t
:mode "\\.json\\'")
;; Flycheck (syntax checking)
(use-package flycheck
:ensure t
:init (global-flycheck-mode)
:config
(setq-default flycheck-disabled-checkers '(emacs-lisp-checkdoc)))
;; Auto-formatting
(use-package format-all
:ensure t
:hook (prog-mode . format-all-mode))