Emacs: The Extensible Editor
GNU Emacs is one of the most powerful and extensible text editors available. Created by Richard Stallman in 1976, Emacs is more than just an editor—it’s a complete computing environment that can be customized and extended using Emacs Lisp.
Why Choose Emacs?
- Extreme extensibility: Customize everything with Emacs Lisp
- Integrated environment: Email, calendar, file manager, shell, and more
- Powerful editing: Advanced text manipulation and programming features
- Linux integration: Deep integration with Linux development workflows
- Active community: Thousands of packages and configurations
- Self-documenting: Comprehensive built-in help system
- Org-mode: Powerful organization and note-taking system
- System administration: Excellent for managing Linux servers and configurations
Installation
Linux Distributions
# Ubuntu/Debian
sudo apt update
sudo apt install emacs
# For GUI version
sudo apt install emacs-gtk
# CentOS/RHEL/Fedora
sudo yum install emacs
# or
sudo dnf install emacs
# Arch Linux
sudo pacman -S emacs
# Alpine Linux
sudo apk add emacs
Additional Linux Distributions
# SUSE/openSUSE
sudo zypper install emacs
# Gentoo
sudo emerge app-editors/emacs
# Void Linux
sudo xbps-install emacs
# For GUI version on Linux
sudo apt install emacs-gtk # Ubuntu/Debian with GTK
sudo pacman -S emacs # Arch Linux (includes GUI)
Building from Source
# Install dependencies (Ubuntu/Debian)
sudo apt install build-essential texinfo libx11-dev libxpm-dev \
\
libjpeg-dev libpng-dev libgif-dev libtiff-dev libgtk-3-dev
libncurses-dev libxpm-dev automake autoconf
# Download and build
wget https://ftp.gnu.org/gnu/emacs/emacs-29.1.tar.xz
tar -xf emacs-29.1.tar.xz
cd emacs-29.1
./configure --with-native-compilation
make -j$(nproc)
sudo make install
Basic Concepts
Key Notation
C-x
means Ctrl+xM-x
means Alt+x (Meta key)C-x C-f
means Ctrl+x followed by Ctrl+fRET
means Enter keySPC
means Space key
Buffers, Windows, and Frames
- Buffer: A file or content in memory
- Window: A view of a buffer (can have multiple windows)
- Frame: The entire Emacs window (can have multiple frames)
Major and Minor Modes
- Major Mode: Defines the primary editing behavior (e.g., Python mode, HTML mode)
- Minor Mode: Additional features that can be enabled/disabled (e.g., line numbers, auto-complete)
Essential Commands
Starting and Exiting
# Start Emacs
emacs
# Start in terminal mode
emacs -nw
# Open specific file
emacs filename.txt
# Exit Emacs
C-x C-c
File Operations
# Open file
C-x C-f
# Type filename and press RET
# Save file
C-x C-s
# Save as (write file)
C-x C-w
# Save all buffers
C-x s
# Insert file contents
C-x i
# Recent files
C-x C-r
Buffer Management
# Switch buffer
C-x b
# Type buffer name or use TAB completion
# List all buffers
C-x C-b
# Kill (close) buffer
C-x k
# Switch to next buffer
C-x →
# Switch to previous buffer
C-x ←
Window Management
# Split window horizontally
C-x 2
# Split window vertically
C-x 3
# Switch to other window
C-x o
# Delete current window
C-x 0
# Delete other windows
C-x 1
# Resize windows
C-x ^ # Make taller
C-x } # Make wider
C-x { # Make narrower
Search and Replace
Basic Search
# Incremental search forward
C-s
# Type search term, C-s for next occurrence
# Incremental search backward
C-r
# Word search
C-s C-w # Search for word at cursor
# Regular expression search
C-M-s # Forward regex search
C-M-r # Backward regex search
Replace Operations
# Query replace
M-%
# Enter search term, then replacement
# y (yes), n (no), ! (all), q (quit)
# Regular expression replace
C-M-%
# Replace in region
# Select region first, then M-%
Advanced Search
# Occur (show all lines matching pattern)
M-s o
# Multi-occur (search in multiple buffers)
M-s M-o
# Grep in files
M-x grep
M-x rgrep # Recursive grep
Configuration
Init File
Emacs configuration is stored in ~/.emacs.d/init.el
or ~/.emacs
:
;; ~/.emacs.d/init.el - Basic configuration
;; Package management
(require 'package)
(setq package-archives '(("melpa" . "https://melpa.org/packages/")
("org" . "https://orgmode.org/elpa/")
("elpa" . "https://elpa.gnu.org/packages/")))
(package-initialize)
;; Bootstrap 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) ; Disable startup screen
(setq visible-bell t) ; Visual bell instead of beep
(setq make-backup-files nil) ; Disable backup files
(setq auto-save-default nil) ; Disable auto-save
;; UI improvements
(tool-bar-mode -1) ; Disable toolbar
(menu-bar-mode -1) ; Disable menu bar
(scroll-bar-mode -1) ; Disable scroll bar
(global-display-line-numbers-mode 1) ; Show line numbers
(column-number-mode 1) ; Show column numbers
(show-paren-mode 1) ; Highlight matching parentheses
;; Indentation
(setq-default indent-tabs-mode nil) ; Use spaces instead of tabs
(setq-default tab-width 4) ; Tab width
(setq indent-line-function 'insert-tab) ; Tab behavior
;; Font and theme
(set-face-attribute 'default nil :font "Fira Code-12")
(load-theme 'wombat t)
;; Key bindings
(global-set-key (kbd "C-x C-b") 'ibuffer)
(global-set-key (kbd "M-/") 'hippie-expand)
(global-set-key (kbd "C-c c") 'comment-or-uncomment-region)
;; Auto-completion
(use-package company
:ensure t
:init
(global-company-mode 1))
;; Syntax checking
(use-package flycheck
:ensure t
:init
(global-flycheck-mode))
;; Git integration
(use-package magit
:ensure t
:bind ("C-x g" . magit-status))
;; Project management
(use-package projectile
:ensure t
:init
(projectile-mode +1)
:bind-keymap
("C-c p" . projectile-command-map))
;; File tree
(use-package neotree
:ensure t
:bind ("F8" . neotree-toggle))
;; Better search
(use-package ivy
:ensure t
:init
(ivy-mode 1)
:config
(setq ivy-use-virtual-buffers t)
(setq enable-recursive-minibuffers t))
(use-package counsel
:ensure t
:bind (("M-x" . counsel-M-x)
("C-x C-f" . counsel-find-file)
("C-h f" . counsel-describe-function)
("C-h v" . counsel-describe-variable)))
(use-package swiper
:ensure t
:bind ("C-s" . swiper))
Package Management
;; Install packages manually
M-x package-install RET package-name RET
;; List packages
M-x list-packages
;; Update packages
M-x package-list-packages
# Press 'U' then 'x' to update all
Popular Packages
;; Essential packages configuration
;; Helm (alternative to ivy/counsel)
(use-package helm
:ensure t
:bind (("M-x" . helm-M-x)
("C-x C-f" . helm-find-files)
("C-x b" . helm-buffers-list))
:config
(helm-mode 1))
;; Which-key (show key bindings)
(use-package which-key
:ensure t
:config
(which-key-mode))
;; Multiple cursors
(use-package multiple-cursors
:ensure t
:bind (("C-S-c C-S-c" . mc/edit-lines)
("C->" . mc/mark-next-like-this)
("C-<" . mc/mark-previous-like-this)))
;; Expand region
(use-package expand-region
:ensure t
:bind ("C-=" . er/expand-region))
;; Yasnippet (snippets)
(use-package yasnippet
:ensure t
:config
(yas-global-mode 1))
;; Language Server Protocol
(use-package lsp-mode
:ensure t
:hook ((python-mode . lsp)
(js-mode . lsp)
(typescript-mode . lsp))
:commands lsp)
(use-package lsp-ui
:ensure t
:commands lsp-ui-mode)
;; Company LSP integration
(use-package company-lsp
:ensure t
:commands company-lsp)
Programming with Emacs
Language-Specific Modes
;; Python development
(use-package python-mode
:ensure t
:mode "\\.py\\'"
:config
(setq python-indent-offset 4))
;; JavaScript/TypeScript
(use-package js2-mode
:ensure t
:mode "\\.js\\'"
:config
(setq js2-basic-offset 2))
(use-package typescript-mode
:ensure t
:mode "\\.ts\\'")
;; Web development
(use-package web-mode
:ensure t
:mode ("\\.html\\'" "\\.css\\'" "\\.jsx\\'")
: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\\'")
;; YAML
(use-package yaml-mode
:ensure t
:mode "\\.ya?ml\\'")
;; JSON
(use-package json-mode
:ensure t
:mode "\\.json\\'")
Debugging
;; GDB integration
M-x gdb
;; Python debugging with pdb
M-x pdb
;; Edebug (Emacs Lisp debugger)
C-u C-M-x ; Instrument function for debugging
Org Mode
Org-mode is one of Emacs’ most powerful features for organization and note-taking:
Basic Org Syntax
* Top Level Heading
** Second Level Heading
*** Third Level Heading
- Unordered list item
- Another item
- Sub-item
1. Ordered list item
2. Another ordered item
*bold* /italic/ _underlined_ =code= ~verbatim~
[[https://example.com][Link text]]
#+BEGIN_SRC python
def hello_world():
print("Hello, World!")
#+END_SRC
| Name | Age | City |
|------+-----+------|
| John | 25 | NYC | | Jane | 30 | LA |
Org Mode Commands
# Structure editing
TAB # Cycle visibility
S-TAB # Global visibility cycling
M-RET # Insert new heading
M-←/→ # Promote/demote heading
M-↑/↓ # Move heading up/down
# TODO items
C-c C-t # Cycle TODO states
C-c C-s # Schedule item
C-c C-d # Set deadline
# Tables
C-c | # Create table
TAB # Move to next field
S-TAB # Move to previous field
C-c C-c # Align table
# Links
C-c C-l # Insert link
C-c C-o # Open link
# Export
C-c C-e # Export menu
Org Configuration
;; Org-mode configuration
(use-package org
:ensure t
:config
(setq org-todo-keywords
'((sequence "TODO" "IN-PROGRESS" "WAITING" "|" "DONE" "CANCELLED")))
(setq org-agenda-files '("~/org/"))
(setq org-default-notes-file "~/org/notes.org")
:bind (("C-c l" . org-store-link)
("C-c a" . org-agenda)
("C-c c" . org-capture)))
;; Org capture templates
(setq org-capture-templates
'(("t" "Todo" entry (file+headline "~/org/tasks.org" "Tasks")
"* TODO %?\n %i\n %a")
("n" "Note" entry (file+headline "~/org/notes.org" "Notes")
"* %?\nEntered on %U\n %i\n %a")))
Real-World Development Scenarios
Scenario 1: Python Development Setup
;; Python development configuration
(use-package python-mode
:ensure t
:config
(setq python-indent-offset 4)
(add-hook 'python-mode-hook
(lambda ()
(setq indent-tabs-mode nil)
(setq tab-width 4)
(setq python-indent-offset 4))))
;; Virtual environment support
(use-package pyvenv
:ensure t
:config
(pyvenv-mode 1))
;; Python testing
(use-package python-pytest
:ensure t
:bind (:map python-mode-map
("C-c t" . python-pytest)))
;; Jupyter notebooks
(use-package ein
:ensure t)
Scenario 2: Web Development Workflow
;; Web development setup
(use-package web-mode
:ensure t
:mode ("\\.html\\'" "\\.css\\'" "\\.js\\'" "\\.jsx\\'" "\\.tsx\\'")
:config
(setq web-mode-markup-indent-offset 2)
(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))
;; Emmet for HTML expansion
(use-package emmet-mode
:ensure t
:hook (web-mode . emmet-mode))
;; Live browser reload
(use-package impatient-mode
:ensure t)
;; REST client
(use-package restclient
:ensure t
:mode ("\\.http\\'" . restclient-mode))
Scenario 3: System Administration
;; System administration tools
(use-package tramp
:config
(setq tramp-default-method "ssh"))
;; Docker integration
(use-package docker
:ensure t
:bind ("C-c d" . docker))
(use-package dockerfile-mode
:ensure t
:mode "Dockerfile\\'")
;; Ansible
(use-package ansible
:ensure t)
;; Log file viewing
(use-package logview
:ensure t
:mode ("\\.log\\'" . logview-mode))
Advanced Emacs Features
Macros
# Record macro
C-x ( # Start recording
# ... perform actions ...
C-x ) # Stop recording
# Execute macro
C-x e # Execute once
C-u 10 C-x e # Execute 10 times
# Name and save macro
M-x name-last-kbd-macro
M-x insert-kbd-macro
Registers
# Save to register
C-x r s a # Save region to register 'a'
C-x r i a # Insert from register 'a'
# Save position
C-x r SPC a # Save position to register 'a'
C-x r j a # Jump to register 'a'
# Save window configuration
C-x r w a # Save window config to register 'a'
C-x r j a # Restore window config from register 'a'
Dired (Directory Editor)
# Open dired
C-x d
# Dired commands
RET # Open file/directory
q # Quit dired
g # Refresh
m # Mark file
u # Unmark file
d # Mark for deletion
x # Execute deletions
C # Copy file
R # Rename/move file
+ # Create directory
Shell Integration
# Shell commands
M-! # Execute shell command
M-| # Shell command on region
C-u M-! # Insert command output
# Shell mode
M-x shell
M-x eshell # Emacs shell
M-x term # Terminal emulator
Customization and Themes
Custom Themes
;; Popular themes
(use-package doom-themes
:ensure t
:config
(load-theme 'doom-one t))
(use-package solarized-theme
:ensure t)
(use-package zenburn-theme
:ensure t)
;; Theme switching function
(defun switch-theme (theme)
"Disable current theme and load THEME."
(interactive
(list
(intern (completing-read "Load custom theme: "
(mapcar 'symbol-name
(custom-available-themes))))))
(let ((enabled-themes custom-enabled-themes))
(mapc #'disable-theme custom-enabled-themes)
(load-theme theme t)))
Custom Functions
;; Useful custom functions
(defun duplicate-line ()
"Duplicate current line."
(interactive)
(move-beginning-of-line 1)
(kill-line)
(yank)
(open-line 1)
(next-line 1)
(yank))
(global-set-key (kbd "C-c d") 'duplicate-line)
(defun comment-or-uncomment-region-or-line ()
"Comments or uncomments the region or the current line if there's no active region."
(interactive)
(let (beg end)
(if (region-active-p)
(setq beg (region-beginning) end (region-end))
(setq beg (line-beginning-position) end (line-end-position)))
(comment-or-uncomment-region beg end)))
(global-set-key (kbd "C-/") 'comment-or-uncomment-region-or-line)
Performance Optimization
Startup Optimization
;; Startup optimization
(setq gc-cons-threshold (* 50 1000 1000)) ; Increase GC threshold
(setq read-process-output-max (* 1024 1024)) ; Increase read buffer
;; Restore GC threshold after startup
(add-hook 'emacs-startup-hook
(lambda ()
(setq gc-cons-threshold (* 2 1000 1000))))
;; Lazy loading
(use-package package-name
:ensure t
:defer t ; Lazy load
:hook (mode . package-name))
Large File Handling
;; Large file handling
(defun my-find-file-check-make-large-file-read-only-hook ()
"If a file is over a given size, make the buffer read only."
(when (> (buffer-size) (* 1024 1024))
(setq buffer-read-only t)
(buffer-disable-undo)
(fundamental-mode)))
(add-hook 'find-file-hook 'my-find-file-check-make-large-file-read-only-hook)
Troubleshooting
Common Issues
# Debug init file
emacs --debug-init
# Start with minimal config
emacs -Q
# Profile startup time
M-x emacs-init-time
# Check package issues
M-x package-list-packages
# Look for packages with issues
# Reset package system
# Delete ~/.emacs.d/elpa/ and restart
Recovery
# Auto-save recovery
M-x recover-file
# Session recovery
M-x desktop-save-mode ; Enable session saving
M-x desktop-read ; Restore session
Emacs is incredibly powerful and customizable, making it suitable for everything from simple text editing to complex development workflows. While it has a steep learning curve, the investment pays off with a highly personalized and efficient editing environment.