Helm is a pretty neat package that adds more effective navigation commands to Emacs. This requires it and sets keyboard shortcuts and other stuff.
If you want to use the Dash/Zeal integration, you’ll need that. Also, if you
want to use GTAGS (which are the bee’s knees), you’ll need GNU Global. For
Arch, just do yaourt -S global
, since it’s an AUR package.
Additionally, when you use GTAGS with a C project, you’ll need to go to the
project root and use the command gtags
.
We need Helm. Also, Helm-Dash provides integration with Dash/Zeal. I haven’t really used it, so Helm-Dash could be a candidate for deletion someday. Finally, we want to also have Helm-Gtags, so that you can jump to tag definitions within your project.
(require-package '(helm helm-dash helm-gtags))
(require 'helm-config)
(require 'helm-gtags)
The default “C-x c” is quite close to “C-x C-c”, which quits Emacs. I changed it to “C-c h”. Note: We must set “C-c h” globally, because we cannot change `helm-command-prefix-key’ once `helm-config’ is loaded.
;; The default "C-x c" is quite close to "C-x C-c", which quits Emacs.
;; Changed to "C-c h". Note: We must set "C-c h" globally, because we
;; cannot change `helm-command-prefix-key' once `helm-config' is loaded.
(global-set-key (kbd "C-c h") 'helm-command-prefix)
(global-unset-key (kbd "C-x c"))
Adjust key bindings for the actual Helm completion mode.
(eval-after-load 'helm
'(progn
; rebind tab to do persistent action
(define-key helm-map (kbd "<tab>") 'helm-execute-persistent-action)
; make TAB works in terminal
(define-key helm-map (kbd "C-i") 'helm-execute-persistent-action)
; list actions using C-z
(define-key helm-map (kbd "C-z") 'helm-select-action)
))
This appears to add a Google search option. It shows suggestions, which is
nice. And it opens in a browser, not in eww
.
(when (executable-find "curl")
(setq helm-google-suggest-use-curl-p t))
Here we have some Helm options, which are mostly self-documented.
(setq
; do not display invisible candidates
helm-quick-update t
; open helm buffer inside current window, not occupy whole other window
helm-split-window-in-side-p t
; fuzzy matching buffer names when non--nil
helm-buffers-fuzzy-matching t
; move to end or beginning of source when reaching top or bottom of source.
helm-move-to-line-cycle-in-source t
; search for library in `require' and `declare-function' sexp.
helm-ff-search-library-in-sexp t
; scroll 8 lines other window using M-<next>/M-<prior>
helm-scroll-amount 8
helm-ff-file-name-history-use-recentf t)
Here I will actually rebind some basic Emacs navigation commands to their helm equivalents.
helm-M-x
gives you much nicer searching capabilities through the mess of possible commands in the M-x menu.helm-show-kill-ring
is a ridiculously convenient replacement for the normal “yank cycling” ability Emacs has by default. When you want to yank something you killed a few kills before, the default is to just hit M-y a bunch of times, until you find your killed text in the kill ring. But with the Helm version, M-y just pops up a menu that shows the kill rink, and you can navigate through and hit Enter on the one you want to yank! Much nicer.helm-mini
gives you a buffer selection panel with the fuzzy matching we love. It also gives you a recent file list that’s searchable, so you can load recent files that you maybe forgot that you killed.helm-find-files
is the fuzzy-matching version of C-x C-f. It is a quite worthy replacement for the original. You can use patterns to narrow down the listing of files by extension, etc.
(global-set-key (kbd "M-x") 'helm-M-x)
(global-set-key (kbd "M-y") 'helm-show-kill-ring)
(global-set-key (kbd "C-x b") 'helm-mini)
(global-set-key (kbd "C-x C-f") 'helm-find-files)
And finally, we turn on Helm.
(helm-mode 1)
This configures Helm Dash, which lets you search Zeal/Dash docsets from a Helm
buffer. I’m setting it up to work with eww
so I don’t have to switch windows.
(setq helm-dash-browser-func 'eww)
(setq helm-dash-docsets-path (expand-file-name "~/.local/share/Zeal/Zeal/docsets"))
(global-set-key (kbd "C-c h d") 'helm-dash)
Here are a bunch of language hooks that will set the docsets I want available for each lanugage mode.
(add-hook 'c-mode-hook
(lambda ()
(setq-local helm-dash-docsets '("C"))))
(add-hook 'cpp-mode-hook
(lambda ()
(setq-local helm-dash-docsets '("C++"))))
(add-hook 'python-mode-hook
(lambda ()
(setq-local helm-dash-docsets '("Python 3" "Django" "Flask" "NumPy"
"SciPy"))))
(add-hook 'java-mode-hook
(lambda
(setq-local helm-dash-docsets '("Java SE7"))))
Now here we set up Helm Gtags. A good deal of this code came from this C IDE
article. It is a wonderful resource for C, CEDET, Company Mode, Helm,
etc. related configuration. This section of setq
’s is mostly self
documenting.
(setq
helm-gtags-ignore-case t
helm-gtags-auto-update t
helm-gtags-use-input-at-cursor t
helm-gtags-pulse-at-cursor t
helm-gtags-prefix-key "\C-cg"
helm-gtags-suggested-key-mapping t
)
There is a Helm Gtags minor mode that has to be enabled on C/C++ files. This does so.
;; Enable helm-gtags-mode
(add-hook 'dired-mode-hook 'helm-gtags-mode)
;(add-hook 'eshell-mode-hook 'helm-gtags-mode)
(add-hook 'c-mode-hook 'helm-gtags-mode)
(add-hook 'c++-mode-hook 'helm-gtags-mode)
(add-hook 'asm-mode-hook 'helm-gtags-mode)
Finally, this is a list of the suggested keybindings for Helm Gtags taken from the above article. I fully agree with them!
(define-key helm-gtags-mode-map (kbd "C-c g a") 'helm-gtags-tags-in-this-function)
(define-key helm-gtags-mode-map (kbd "C-j") 'helm-gtags-select)
(define-key helm-gtags-mode-map (kbd "M-.") 'helm-gtags-dwim)
(define-key helm-gtags-mode-map (kbd "M-,") 'helm-gtags-pop-stack)
(define-key helm-gtags-mode-map (kbd "C-c <") 'helm-gtags-previous-history)
(define-key helm-gtags-mode-map (kbd "C-c >") 'helm-gtags-next-history)
(define-key helm-gtags-mode-map (kbd "C-c g r") 'helm-gtags-find-rtag)
(define-key helm-gtags-mode-map (kbd "C-c g s") 'helm-gtags-find-symbol)
Using Helm takes some getting used to. I’m not going to document the features of Helm here, but there are good resources out there (accessible by Google). For the main features of Helm, I’ve set it up so that default Emacs keybindings are rebound to Helm equivalents.
For Helm Dash, you simply use C-c h d (think “C-c helm dash”). Then you can search for documents.
For Helm GTAGS, there is a whole host of goodies. These really only apply to C and C++, but they have to be configured with Helm, so I placed the configuration and instructions here.
- With point on a tag name (like a function), use M-. to go to its definition.
- To return from a definition visit, use M-, .
- You can use the C-c < or C-c > to go through your tag visiting history. I’m not sure how that differs from using M-,.
- There is a keyboard shortcut (C-c g a) to find all tags in your function. I’m not really sure how helpful that is though.
- With point on a tag name, use “C-c g r” to find references! Oh so useful.