- Published on
Xây dựng một cấu hình Emacs từ đầu
- Authors
- Name
- Viet Anh
- @vietanhdev
Emacs là một trình soạn thảo văn bản đa chức năng và có thể mở rộng các chức năng một cách mạnh mẽ. Khi chưa cấu hình (tất cả thiết lập để ở mặc định), Emacs có thể coi là trình soạn thảo hơi khó dùng, giao diện khá đơn giản, nếu không nói là xấu. Tuy nhiên khi tuỳ biến bằng các tệp cấu hình, bạn có thể biến Emacs thành bất cứ thứ gì bạn muốn. Đó là lý do Emacs có thể tồn tại được từ lần đầu tiên nó được sinh ra (năm 1976) cho tới nay và luôn là một trong các trình soạn thảo code được nhiều lập trình viên sử dụng nhất. Trong bài viết này tôi sẽ hướng dẫn các bạn cấu hình cơ bản Emacs từ đầu cho tới khi trở thành một trình soạn thảo đem lại cho bạn cảm giác thoải mái.
Một số hình ảnh về Emacs sử dụng các cấu hình khác nhau:

GNU Emacs cấu hình mặc định - Hình ảnh từ trang chủ.

Spacemacs - Một cấu hình Emacs được phát triển bởi cộng đồng

Bản Emacs với cấu hình tôi đang dùng để viết bài viết này và sẽ hướng dẫn các bạn tạo một cái tương tự.
Tệp cấu hình Emacs ở đâu?
Bạn có thể chỉnh sửa cấu hình Emacs tại file ~/.emacs.el
hoặc ~/.emacs.d/init.el
.
Trong khuôn khổ bài viết này, tôi chỉ hướng dẫn các bạn cấu hình từ đầu bằng cách dùng file ~/.emacs.d/init.el
. Bạn có thể sử dụng bất kì editor nào bạn muốn để thực hiện việc chỉnh sửa file này (có thể là chính Emacs, tuy nhiên bạn sẽ phải mở lại file cấu hình liên tục mỗi khi khởi động lại Emacs để xem kết quả nếu bạn dùng nó).
Tạo file cấu hình từ đầu
Hãy tạo 1 file cấu hình để chúng ta bắt đầu làm việc từ đầu bằng cách xoá file ~/.emacs.el
và tất cả các file trong thư mục ~/.emacs.d
, sau đó tạo file mới ~/.emacs.d/init.el
.
Sau khi có một file cấu hình mới tên init.el
, bạn hãy thực hiện tiếp các bước bên dưới để thêm nội dung vào.
Nạp package manager
Package manager (giống Package control bên Sublime Text) giúp bạn quản lí, cài đặt các gói tính năng bổ sung cho trình soạn thảo.
Thêm đoạn code sau để load package manager lên và thêm kho plugin "melpa":
;; Load package manager
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
(package-initialize)
Trong bài viết này tôi sẽ sử dụng thêm một gói tên use-package
để tự động quản lí việc tải về các package khác và tăng đáng kể tốc độ khởi động Emacs.
Đặt đoạn code sau ngay phía dưới đoạn trên:
;; Load `use-package`
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))
(eval-when-compile
(require 'use-package))
(require 'diminish)
(require 'bind-key)
(setq use-package-always-ensure t)
Tuỳ biến các giao diện chính
Đổi theme
Trong cấu hình này tôi sẽ sử dụng theme monokai (theme màu tối được khá nhiều người ưa thích). Bạn cũng có thể tìm các theme khác từ Google nhé.
;; Load editor theme
(use-package monokai-theme
:config (load-theme 'monokai t))
Ẩn các thanh công cụ, menu, thanh cuộn mặc định
Đôi khi việc có thêm các thanh menu, thanh cuộn chỉ làm bạn mất tập trung. Hãy loại bỏ chúng bằng cách thêm đoạn code sau (Lưu ý nếu bạn muốn giữ lại thứ gì hãy comment lại dòng tương ứng bằng cách để dấu ;
ở đầu dòng).
;; Turn off menubar, toolbar, scollbar
(if (fboundp 'menu-bar-mode) (menu-bar-mode -1))
(if (fboundp 'tool-bar-mode) (tool-bar-mode -1))
(if (fboundp 'scroll-bar-mode) (scroll-bar-mode -1))

Hiện line number (số dòng khi soạn code)
;; Display line number when programming
(add-hook 'prog-mode-hook 'linum-mode)
(setq linum-format "%4d \u2502")
Cài đặt tab-indent
(setq tab-width 4)
Word wrap
Mặc định Emacs sẽ cắt dòng bằng cách cắt đôi một từ. Dòng sau sẽ giúp cài đặt Emacs chỉ xuống dòng khi viết hết từ.
(global-visual-line-mode t)
Tô sáng các ngoặc tương ứng nhau
Sử dụng code sau giúp tô sáng ngoặc tương ứng khi bạn để con trỏ lên một ngoặc.
;; Display paren (highlight matching brackets)
(show-paren-mode 1)
(setq show-paren-delay 0)
Đổi Font chữ
Tôi rất thích sử dụng font "Source Code Pro" của Adobe khi code. Do vậy tôi sẽ đổi font mặc định của Emacs:
Cài Font "Source Code Pro" của Adobe bằng cách tải về từ github https://github.com/adobe-fonts/source-code-pro và thực hiện cài đặt theo hệ điều hành sử dụng.
Sau khi cài font "Source Code Pro", thêm đoạn sau vào file cấu hình Emacs:
(set-face-attribute 'default nil
:family "Source Code Pro"
:height 160
:weight 'normal
:width 'normal)
Cá nhân hoá "Lời chào" khi khởi động Emacs
Có một cấu hình khác hay trong Emacs giúp bạn tạo ra một màn hình "Lời chào" mỗi khi bật Emacs thay vì màn hình trợ giúp mặc định của nó. Thêm code sau vào file cấu hình (sửa lời chào của tôi thành cái của bạn nhé - có thể dùng markdown để lời chào thêm sinh động).
;; Display startup message
(setq initial-scratch-message "
# EMACS CONFIGURATION BY VIET-ANH NGUYEN
# VERSION : 1.0
## Email: ...
## Website: ...
## Welcome! Hope my configuration can help you.
")
(setq inhibit-startup-message t)
(setq initial-major-mode 'markdown-mode)
Well done!
Kết thúc phần cấu hình giao diện cơ bản. Bạn có thể khởi động lại Emacs để xem những thay đổi vừa xảy ra rồi đó. Nếu có bất kì thắc mắc hoặc vấn đề nào trong quá trình thực hiện, hãy comment bên dưới bài viết.
Một số tuỳ biến giao diện nâng cao
Cuộn trang mượt hơn, chế độ xem thẩm mĩ và minimap giống Sublime Text
Nếu bạn lựa chọn trình soạn thảo Sublime Text vì những thứ trên và ghét Emacs ở chỗ mỗi khi bạn cuộn trang (C-v, M-v) thì Emacs sẽ ngay lập tức chuyển sang vị trí tiếp theo, không có hiệu ứng cuộn, hay bạn thích 1 trình soạn thảo có thêm chức năng minimap("bản đồ" thu nhỏ của code), xem văn bản kiểu attractive (căn lề 2 bên để tăng tính thẩm mĩ), xin trả lời Emacs cũng làm được như vậy với package sublimity. Chỉ cần thêm đoạn code sau:
;; Smooth Scrolling and attractive mode (look like Sublime Text)
(use-package sublimity
:config
(require 'sublimity-scroll)
;; (require 'sublimity-map) ;; experimental
(require 'sublimity-attractive)
(sublimity-mode 1)
)
Cá nhân tôi không thích chế độ xem minimap nên tôi sẽ comment dòng ;; (require 'sublimity-map) ;; experimental
. Chỉ cần bỏ ;;
đầu dòng đó là chức năng trên sẽ được kích hoạt.
Screenshot (Nguồn sublimity):

Thêm chức năng Directory view (Hiện cây thư mục các file trong dự án ở bên trái)
Ở đây mình sẽ sử dụng đến package tên "neotree" cho chức năng hiện cây thư mục và "all-the-icons" cho hiển thị các icon đẹp cho thư mục và tệp.
Cài all-the-icons
Thêm dòng:
(use-package all-the-icons)
Tiếp theo, khởi động lại Emacs và gõ M-x all-the-icons-install-fonts
để cài các icon font vào hệ thống.
Cài neotree
;; Display a directory tree view on the left side
(use-package neotree
:config (progn
(setq neo-theme (if (display-graphic-p) 'icons 'arrow)))
:bind ("C-x n o" . neotree-toggle))
Sau khi khởi động lại một lần nữa và chờ tới khi neotree được cài đặt, bạn có thể gõ C-x n o
để bật/tắt chế độ xem cây thư mục.
Screenshot

Thêm NyanCat (hình con mèo bay) ở dưới thanh Modeline để biểu thị vị trí chuột so với văn bản
;; NyanCat on Modeline as an analog indicator of your position in the buffer
(use-package nyan-mode
:config
(nyan-mode)
)
Bạn có thể ghé qua https://github.com/TeMPOraL/nyan-mode để tìm hiểu thêm một số thiết lập animation (hoạt hình) cho NyanCat.
Hình ảnh thanh NyanCat:

Tăng cường chức năng tìm kiếm và tự động hoàn thành
Thay thế chức năng tìm kiếm, tự hoàn thành mặc định bằng Ivy
Các chức năng tìm kiếm, tự hoàn thành mặc định có thể thay thế bằng một framework tuyệt vời tên Ivy. Bạn cũng có thể dùng Helm - framework khá mạnh mẽ được nhiều người dùng. Tuy nhiên vì Helm có quá nhiều chức năng, nó sẽ khiến Emacs chậm đi đáng kể tôi quyết định chọn Ivy.
Thêm đoạn code sau vào file cấu hình và khởi động lại. Thử một chức năng như tìm kiếm C-s hay M-x để xem sự khác biệt so với các mặc định của Emacs.
;; Replace default completion frontend with Ivy
;; https://github.com/abo-abo/swiper
(use-package counsel
:config (ivy-mode 1)
:init
(progn
(setq ivy-use-virtual-buffers t)
(setq enable-recursive-minibuffers t)
(global-set-key "\C-s" 'swiper)
(global-set-key (kbd "C-c C-r") 'ivy-resume)
(global-set-key (kbd "<f6>") 'ivy-resume)
(global-set-key (kbd "M-x") 'counsel-M-x)
(global-set-key (kbd "C-x C-f") 'counsel-find-file)
(global-set-key (kbd "<f1> f") 'counsel-describe-function)
(global-set-key (kbd "<f1> v") 'counsel-describe-variable)
(global-set-key (kbd "<f1> l") 'counsel-find-library)
(global-set-key (kbd "<f2> i") 'counsel-info-lookup-symbol)
(global-set-key (kbd "<f2> u") 'counsel-unicode-char)
(global-set-key (kbd "C-c g") 'counsel-git)
(global-set-key (kbd "C-c j") 'counsel-git-grep)
(global-set-key (kbd "C-c k") 'counsel-ag)
(global-set-key (kbd "C-x l") 'counsel-locate)
(global-set-key (kbd "C-S-o") 'counsel-rhythmbox)
(define-key read-expression-map (kbd "C-r") 'counsel-expression-history))
)
Tự hoàn thành code và chức năng Snippet
Autocomplete : company
;; Autocomplete
(use-package company
:config (global-company-mode t))
Thêm các snippets từ gói yasnippet cho nhiều ngôn ngữ
;; Snippets
(use-package yasnippet
:defer t
:init
(yas-global-mode 1))
Tự động check lỗi lập trình theo thời gian thực
Ở đây tôi dùng Flycheck thay cho Flymake mặc định trên Emacs.
;;;; FLYCHECK - REALTIME ERROR CHECKING ===============
(use-package flycheck
:config
(global-flycheck-mode)
(setq flycheck-check-syntax-automatically '(mode-enabled save))
)
Thêm một số phím tắt chức năng cho Emacs
Comment/Uncomment các dòng code
Thêm đoạn code sau và bạn có chức năng comment tương tự các editor khác như Sublime Text (sử dụng C-c c
để toggle comment cho các dòng code được bôi đen).
(defun xah-comment-dwim ()
"Like `comment-dwim', but toggle comment if cursor is not at end of line."
(interactive)
(if (region-active-p)
(comment-dwim nil)
(let ((-lbp (line-beginning-position))
(-lep (line-end-position)))
(if (eq -lbp -lep)
(progn
(comment-dwim nil))
(if (eq (point) -lep)
(progn
(comment-dwim nil))
(progn
(comment-or-uncomment-region -lbp -lep)
(forward-line )))))))
(global-set-key (kbd "C-c c") 'xah-comment-dwim)
Quản lí các buffer
;; Manage buffers
(defun switch-to-previous-buffer ()
"Switch to previously open buffer.
Repeated invocations toggle between the two most recently open buffers."
(interactive)
(switch-to-buffer (other-buffer (current-buffer) 1)))
(use-package key-chord
:config
(progn
(key-chord-mode 1)
(key-chord-define-global "jj" 'switch-to-previous-buffer)
(key-chord-define-global "kk" 'next-buffer))
(key-chord-define-global "gg" 'goto-line)
(key-chord-define-global "yy" 'other-window)
(key-chord-define-global "xx" 'kill-buffer))
Ở đây tôi dùng các keychord
để quản lí các buffer. Keychord được kích hoạt bằng cách ấn liên tục chuỗi phím trên bàn phím. Ví dụ bạn có thể ấn liên tiếp jj
để chuyển qua buffer trước đó. Các keychord dùng quản lí buffer và chức năng của chúng được mô tả trong bảng dưới đây.
Keychord | Function |
---|---|
jj | Chuyển qua buffer trước đó |
kk | Chuyển qua buffer sau |
gg | Đi tới một dòng (Nhập vào số dòng) |
yy | Nhảy giữa các buffer trên màn hình |
xx | Đóng buffer (kill) |
Di chuyển giữa các cửa sổ (buffer đang hiện trên màn hình)
Việc này sẽ được thực hiện bằng cách ấn C-c và theo sau là một phím mũi tên.
;; Move between windows
(global-set-key (kbd "C-c <left>") 'windmove-left)
(global-set-key (kbd "C-c <right>") 'windmove-right)
(global-set-key (kbd "C-c <up>") 'windmove-up)
(global-set-key (kbd "C-c <down>") 'windmove-down)
Thay đổi thích thước các cửa sổ
Việc này được thực hiện bằng cách ấn C-s (phím Ctrl và phím cửa sổ, command) cùng lúc với một phím mũi tên.
;; Resize windows
(global-set-key (kbd "C-s-<left>") 'shrink-window-horizontally)
(global-set-key (kbd "C-s-<right>") 'enlarge-window-horizontally)
(global-set-key (kbd "C-s-<down>") 'shrink-window)
(global-set-key (kbd "C-s-<up>") 'enlarge-window)
Multiple cursors (đa con trỏ)
Đây là một trong những chức năng khá hay trong các editor hiện đại giúp lập trình viên chỉnh sửa cùng lúc nhiều dòng code. Việc này được cài đặt trên Emacs bằng cách sử dụng package multiple-cursors.
;;;; MULTIPLE CURSORS ==================================
(use-package multiple-cursors
:bind (("C-x c" . mc/edit-lines)
("C->" . mc/mark-next-like-this)
("C-<" . mc/mark-previous-like-this)
("C-c C-<" . mc/mark-all-like-this)
("C-S-<down-mouse-1>" . mc/add-cursor-on-click)
)
)
;;;; ===================================================
Xem thêm về cách sử dụng và các cấu hình khác tại multiple-cursors.
Một demo về sử dụng package này trên Emacs Rocks:
http://emacsrocks.com/e13.html
Kết
Trên đây là hướng dẫn cơ bản giúp bạn có được một bản Emacs hoàn chỉnh nhìn khá ổn về giao diện và các chức năng cơ bản. Hãy nhớ khởi động lại Emacs để các package được tải về và cấu hình đúng. Comment bên dưới nếu bạn có góp ý gì cho bài viết của tôi hoặc gặp vấn đề gì với việc cấu hình Emacs.
Tôi đã xây dựng file cấu hình gồm các thiết lập như ở trên kèm theo nhiều chức năng mới hỗ trợ việc phát triển web, ruby, python... và tối ưu hoá thời gian khởi động. Nếu bạn quan tâm có thể truy cập: https://github.com/vietanhdev/VAEmacs-configuration