Best ever programmer text editor: Emacs

I was using jEdit. And once willing to change to, so called modern text editor, Atom Text Editor. Then I did some comparisons among the text editors. At the end, now my primary text editor for coding is Emacs.

Emacs requires some time to learn and practise. But at the end, I love it too much. It is so powerful, no other text editor to compare with it. But the primary usage is for coding.

What are the advantages? It has various powerful addons (packages). It is highly customisable. It can work in command-line, that means you can use it over the SSH. (But normally I use Vim instead.) Like Vim, it can browse a directory. It can also perform diff and merge (but I use meld usually). It can work with gdb for debugging. It has syntax highlighting on different languages. It can perform different indentation based on various languages. Syntax highlighting can work on web development which combines JavaScript, CSS, HTML, and even PHP (using “web mode”). It can save the opened files as a project, so that you can work on multiple projects. It can split the views vertically and horizontally, basically unlimited splits. If you want, you can play Tetris in it. It can be used as window manager too.

There are several modes that are interesting. I suggest to know these modes:

  • dired – Directory browsing
  • ibuffer – List and manage opened files
  • eshell – Emacs shell, like bash
  • ielm – Inferior Emacs Lisp Mode. Interactive Lisp environment
  • w3m – w3m web browser, requires package installation.
  • eww – Default web browser in Emacs, but I found it is difficult to use compared to w3m

Customising Emacs to fit your pattern requires some time.

Just share my .emacs file,

 ;; 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.
 '(buffers-menu-max-size 10)
 '(column-number-mode 1)
 '(ediff-split-window-function (quote split-window-horizontally))
 '(inhibit-startup-screen t)
 '(show-paren-mode t)
 '(tool-bar-mode nil))
 ;; 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.
 '(default ((t (:family "DejaVu Sans Mono" :foundry "unknown" :slant normal :weight normal :height 113 :width normal)))))

;; Emacs default setting
(desktop-save-mode 1)
(global-linum-mode 1)
(savehist-mode 1)
(global-auto-revert-mode t)
(setq column-number-mode 1)
(delete-selection-mode 1)

(setq backup-inhibited t)
(setq auto-save-default nil)
(setq mouse-drag-copy-region nil)

(setq-default indent-tabs-mode nil) ;;Disable indent tabs globally
;;Create my own function
(defun my-toggle-tab ()
  (if (default-value indent-tabs-mode)
        (message "Space indent")
        (setq indent-tabs-mode nil)
      (message "Tab indent")
      (setq indent-tabs-mode t)
(global-set-key (kbd "C-x C-t") 'my-toggle-tab)

;; Very annoying that override the content with delete word
(defun backward-delete-word (arg)
  "Delete characters backward until encountering the beginning of a word.
With argument ARG, do this that many times."
  (interactive "p")
  (delete-region (point) (progn (backward-word arg) (point))))
(global-set-key (kbd "<M-backspace>") 'backward-delete-word)

;; Change font for Chinese characters
(set-fontset-font t 'han (font-spec :family "WenQuanYi Zen Hei Mono"))

;; mouse from
(setq mouse-wheel-scroll-amount '(4 ((shift) . 1))) ;; one line at a time
(setq mouse-wheel-progressive-speed nil) ;; don't accelerate scrolling
(setq mouse-wheel-follow-mouse 't) ;; scroll window under mouse
(setq scroll-step 1) ;; keyboard scroll one line at a time

;; Delete whitespace when save
(add-hook 'before-save-hook 'delete-trailing-whitespace)

;; White space mode
(global-whitespace-mode 1)
(autoload 'whitespace-global-mode "whitespace"
  "Toggle whitespace visualization." t
  (setq whitespace-style (quote (face spaces tabs space-mark tab-mark)))
(autoload 'whitespace-toggle-options "whitespace"
  "Toggle load `whitespace-mode' options." t)

;; Add MELPA
(require 'package)
(add-to-list 'package-archives
	     '("melpa" . ""))
(when (< emacs-major-version 24)
  (add-to-list 'package-archives '("gnu" . "")))

;;Recent file
(require 'recentf)
(recentf-mode 1)
(setq recentf-max-menu-items 15)
(global-set-key (kbd "C-x C-r") 'recentf-open-files)

;; Load undo-tree and set the undo/redo hotkey
(require 'undo-tree)
(global-undo-tree-mode 1)
(global-set-key (kbd "C-z") 'undo-tree-undo)
(global-set-key (kbd "C-S-z") 'undo-tree-redo)

;; Smooth scroll
(require 'smooth-scroll)
(smooth-scroll-mode 1)

;; Enable auto-complete
(require 'auto-complete)
(global-auto-complete-mode 1)

;; Enable hideshowvis to fold and expand the code
;;(require 'hideshowvis)
;;(hideshowvis-minor-mode 1)

;; Make web-mode to indent with 2 spaces,
(require 'web-mode)
(defun my-web-mode-hook ()
  "Hooks for Web mode."
  (setq indent-tabs-mode nil)
  (setq tab-width 4)
  (setq web-mode-markup-indent-offset 2)
  (setq web-mode-css-indent-offset 2)
  (setq web-mode-code-indent-offset 2)
  (setq web-mode-style-padding 0)
  (setq web-mode-script-padding 0)
  (setq web-mode-enable-css-colorization t)
(add-hook 'web-mode-hook  'my-web-mode-hook)

;; Disable csharp-mode tab
(require 'csharp-mode)
(defun my-csharp-mode-fn ()
  "function that runs when csharp-mode is initialized for a buffer."
  (setq indent-tabs-mode nil)
(add-hook  'csharp-mode-hook 'my-csharp-mode-fn t)

;;Auto js2-mode
(autoload 'js2-mode "js2-mode.el" nil t)
(add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))

(autoload 'web-mode "web-mode.el" nil t)
(add-to-list 'auto-mode-alist '("\\.html$" . web-mode))
;; (add-to-list 'auto-mode-alist '("\\.php$" . web-mode))

(autoload 'pkgbuild-mode "pkgbuild-mode.el" "PKGBUILD mode." t)
(setq auto-mode-alist (append '(("/PKGBUILD$" . pkgbuild-mode)) auto-mode-alist))

(require 'w3m-load)
(setq w3m-default-display-inline-images t)

(require 'desktop+) ;;Use the desktop+

;; (autoload 'php-mode "php-mode.el" "Php mode." t)
;; (setq auto-mode-alist (append '(("/*.\.php[345]?$" . php-mode)) auto-mode-alist))
;; (autoload 'python-mode "python-mode.el" "Python mode." t)
;; (setq auto-mode-alist (append '(("/*.\.py$" . python-mode)) auto-mode-alist))

It would be better if you learn Emacs from the beginning and try to adapt the default key bindings (hotkeys). Because, if you replace some of the hotkeys with the ones you are used to, you may miss the default key binding power. No more Ctrl+X, C, or V for cut, copy, and paste. Just learn Emacs and customise it.

One more thing, I was looking for folding (collapse and expand) feature. But failed to find one. Yet, just use the key binding C-M-p and C-M-n are enough to fit my demand.

The following is the video which I screencasted with SimpleScreenRecorder and edited by Blender.