This is a very short post to test my Emacs blogging setup. It will cover only the installation of the packages used for source code review.

I usually review C or Java code (big code bases) and like to do my source code reviews with Emacs, Sourcetrail, and Beyond Compare. All of these tools run on Linux without any problem.

I use Sourcetrail to quickly identify the relationship between software components, and Emacs to navigate the code, take notes (in org-mode), and to write the report (LaTeX). Of course the main reason to use emacs and not other editors is because note taking in org-mode is a killer feature, it is possible to include links to source code lines, add code snippets, include dot diagrams, export to PDF, etc.

What you should be able to do with this setup:

  • Quickly navigate the code
  • “grep” files
  • Use fuzzy matching to find information
  • Take notes efficiently: links and graphs

Pros:

  • Easy to install on new setups.
  • Fuzzy matching. For everything.
  • You can use piped grep results within Emacs to quickly narrow. down your searches It is highly customizable.

Cons:

  • Is not trivial (AFAIK) to use compilation flags to limit searches or code display. The closer I have found is rtags, but it needs compilable code, which I don’t usually have. This can be achieved in Eclipse pretty easily.
  • Languages with function overloads do not play correctly with the

default ctags. You can use a Pygments backend though.

Tools Installation

Needed Tools:

  • Linux
  • Silver searcher (ripgrep can be used but it is currently not in the Debian 9 repositories)
  • Emacs 26
  • GNU global
  • ctags
  • python-pygments

Everything is ready available on Debian repositories, hence the setup is pretty easy to create on a virtual machine or WSL.

This should work on a Debian 9 terminal:

apt-get install emacs25 silversearcher-ag global exuberant-ctags python-pygments

Installing and Configuring Emacs Packages

Use-package

use-package is used to configure emacs packages. It has the benefit of installing the packages if they are not already installed. It makes it easy to move your Emacs setup to a new workstation.

First, setup the packages repositories:

(require 'package) ;; You might already have this line
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/"))

(when (< emacs-major-version 24)
  ;; For important compatibility libraries like cl-lib
  (add-to-list 'package-archives '("gnu" . "http://elpa.gnu.org/packages/")))
(package-initialize) ;; You might already have this line

;; Ensure that use-package is installed, otherwise, install it
(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

(eval-when-compile
  (require 'use-package))
(setq use-package-compute-statistics t)
(require 'use-package-ensure)
(setq use-package-always-ensure t)

Then lets install the following Emacs Packages:

  • helm
  • helm-gtags
  • helm-grep
  • helm-ag
  • eyebrowse
  • helm-projectile
  • projectile
  • ggtags

Gtags

Gtags works with GNU global. The usage is pretty simple. TAG files are created by parsing the source code, and then this tags can be used by ggtags mode to navigate the code

;; Source Code review
;;
;; C mode
;;
(use-package cc-mode
  :defer t
  :config
  (setq c-default-style "linux")

  ;; Change font for functions as I want them
  ;; different than other identifiers.
  (make-face 'font-lock-unnecessary-function)
  (set-face-foreground 'font-lock-unnecessary-function "pink")
  (font-lock-add-keywords 'c-mode
			  '(("\\(\\w+\\)\\s-*\("
			     (1 'font-lock-unnecessary-function))) ;;font-lock-doc-face)))
			  t)

  ;; Open files read-only
  ;;(add-hook 'find-file-hook (lambda () (setq buffer-read-only t)))
  (add-hook 'c-mode-common-hook
	    (lambda ()
	      (when (derived-mode-p 'c-mode 'c++-mode 'java-mode)
		(ggtags-mode t)
		(define-key ggtags-navigation-map (kbd "M-<") nil)
		(setq buffer-read-only t))))

  ;; Highlight whitespace at the end of a line
  (add-hook 'find-file-hook (lambda () (setq show-trailing-whitespace t)))

  ;; Select the parser when following a symbol
  ;;     Semantic: Is aware of the language, it differentiates
  ;;              between local variables or global ones.
  ;;     Helm: Is nicer to see.
  ;;     ggtags: Is the standard way to use gtags
  (setq data '(("Semantic" . semantic-complete-jump-local)
	       ("helm" . helm-gtags-dwim)
	       ("ggtags" . ggtags-find-tag-dwim)))

  (setq helm-source-find-definition
	`((name . "Select the backend")
	  (candidates . ,(mapcar 'car data))
	  (action . (lambda (candidate)
		      (call-interactively (cdr (assoc candidate data)))
		      ))))

  (defun my-find-definition ()
    (interactive)
    (helm :sources 'helm-source-find-definition
	  :buffer "*helm Select parser backend*")))

Helm

helm is a packages that let you select command options when invoked.

;;
;; HELM
;;
(use-package helm
  :ensure t
  :diminish helm-mode
  ;; Helm behavior
  :bind (:map helm-map
              ("<tab>" . helm-execute-persistent-action)
              ("C-i"   . helm-execute-persistent-action)
              ("C-z"   . helm-select-action)
              ("A-v"   . helm-previous-page))
  ;; Global shorcuts
  :bind (("M-x"     . helm-M-x)
         ("M-y"     . helm-show-kill-ring)
         ("M-s '"   . helm-semantic-or-imenu)
	 ("M-s o"   . 'helm-occur)
	 ("M-s M-s" . 'helm-org-in-buffer-headings)
	 ("C-'"     . 'helm-semantic-or-imenu)
	 ("C-c h"   . 'helm-command-prefix)
	 ("C-x b"   . 'helm-mini)
	 ("C-x C-f" . 'helm-find-files)
	 ("C-c f"   . 'helm-recentf)
	 ("C-x C-b" . 'helm-buffers-list))

  :config
  (setq helm-bookmark-show-location t)
  (global-unset-key (kbd "C-x c"))
  ;; fuzzy matching
  (setq helm-mode-fuzzy-match t)
  (setq helm-completion-in-region-fuzzy-match t)
  (setq helm-M-x-fuzzy-match t
        helm-buffers-fuzzy-matching t
        helm-recentf-fuzzy-match t)
  (helm-mode 1))

(use-package helm-gtags
  :defer t
  :ensure t
  :after (helm)
  :bind (("C-."     . 'helm-gtags-dwim)))

(use-package helm-ag
  :ensure t
  :defer t
  :after (helm)
  :config
  (setq helm-ag-insert-at-point 'symbol))