This article helps developers start using Emacs as easily as possible on Linux/Windows/macOS.
Easy/light/good solutions are provided instead of difficult/heavy/perfect solutions.
- Introduction
- Code completion
- Code navigation
- Editing
- Git
- Syntax check
- Compile
- Debug
- Documentation
- Clipboard
- Find file and grep text
- Sub-windows
- Execute command
- Code template
It’s difficult to setup Cedet. Use company-mode instead.
If the C++/Java project is huge (100,000 files for example). Use company-gtags
from company-mode
. GNU Global create tags file for company-gtags
.
company-etags
from company-mode
could be used to replace company-gtags
. It’s slower than company-gtags
. It can handle 10,000 files. Ctags
is used to create tags file. Universal-Ctags is more actively maintained than Exuberant Ctags.
My ~/.ctags.
Use counsel-gtags if company-gtags
is already used.
Use counsel-etags if company-etags
is already used.
Exclude patterns can be used to filter the candidates. For example, input “k1 !neg1 neg2” means candidates should contain string “k1” but neither “neg1” or “neg2”.
Use Evil because most time your are moving cursor in left/right/up/down direction. Evil (Vim emulator) uses hjkl
to do these things.
Evil also gives you chance to use advanced editing techniques like Vim text objects.
Evil is even better than Vim because you can use Emacs Lisp to create your own text object. It’s truly black magic because you can combine the power of Emacs and Vim.
Most people prefer Magit though CLI Git is good enough for me (My ~/.gitconfig).
git-gutter can display diff hunks in current buffer.
The API git-gutter:set-start-revisio
from git-gutter
is very useful.
For example, I created two commands git-gutter-reset-to-header-parent
and git-gutter-reset-to-default
. git-gutter-reset-to-header-parent
display the hunks of HEAD commit. git-gutter-reset-to-default
reset the git-gutter
to its default status:
(require 'git-gutter)
(defun git-gutter-reset-to-head-parent()
(interactive)
(let (parent (filename (buffer-file-name)))
(if (eq git-gutter:vcs-type 'svn)
(setq parent "PREV")
(setq parent (if filename (concat (shell-command-to-string (concat "git --no-pager log --oneline -n1 --pretty=\"format:%H\" " filename)) "^") "HEAD^")))
(git-gutter:set-start-revision parent)
(message "git-gutter:set-start-revision HEAD^")))
(defun git-gutter-reset-to-default ()
(interactive)
(git-gutter:set-start-revision nil)
(message "git-gutter reset"))
Use either built in Flymake or Flycheck.
If you use Flymake, read documentation flymake-allowed-file-name-masks
.
Assign some convenient shortcut to M-x compile
. Learn how to setup compile-comand
,
(setq compile-command "cd ~/projs/proj1 && make && make test")
Try M-x gud-gdb
which is solid.
Setup shortcut for M-x gud-run
.
Gud
and dired
could be programmatically changed, so you can jump to the directory of executable easily.
Google keyword1 keyword2 site:stackoverflow.com
or google keyword1 keyword2 site:github.com filetype:el
.
Use xsel on Linux.
Use pbcopy/pbpaste
on macOS.
Use /dev/clipboard
on Cygwin.
Use powershell.exe -command Get-Clipboard
and clip.exe
on Windows 10.
You need know how to manipulate clipboard through command line for two reasons:
- Traditional way to paste from clipboard could be slow if clipboard content is huge
- Share clipboard between ssh server and client
Install counsle/ivy/swiper (counsel
is dependent on swiper
while swiper is dependent ivy
).
Make sure your project is using git.
M-x counsel-git
to find file.
M-x counsel-git-grep
to use git-grep to grep text in project.
All developer will encounter the problem to find file with similar file name. C++ developers need find “window.hpp” from “window.cpp”. Javascript developers need find “Component.test.js” from “Component.js”.
The easiest solution is just sorting the candidates from counsel-git
by string distance. See LevenshteinDistance.
There are tons of handy commands from these counsel/swiper/ivy (counsel-imenu
, counsel-recentf
, counsel-ibuffer
, …).
API ivy-read
from ivy
is useful. Here is a simple demo on how to use ivy-read
,
(require 'ivy)
(ivy-read "Your choice:"
'("apple" "plum" "orange")
:action (lambda (choice)
(message "I chose %s" choice)))
I usually open 4~8 sub-windows and use winum to move focus between sub-windows.
You need some package to save and load sub-windows layout. You can start from eyebrowse.
Run M-x counsel-M-x
from counsel
.
I prefer using yasnippet
independently instead of as a plugin of company-mode
. So I don’t need think, “OK this candidate is NOT from yasnippet, What I see is what to be inserted. That candidate IS from yasnippet, what I see is not what to be inserted”.