Complete Computing Environment: Programming in Emacs

Table of Contents

Code is my creative outlet. I use it as a way to express myself, as a way to unwind my thoughts in to reality and as a way to build myself a future worth living. My code comes in many forms and serves many purpose. The act of programming, of writing code, is liberating, is freeing, despite the limitations and struggles of using a computer.

I spend a lot of time exploring and dabbling in my free time. I have a wealth of exploratory projects, things built on new ideas and new languages, play toys and future business ideas. These are singular acts of creation, my own children and creations, shared with the people around me as explanations and instructions to understanding my way of grokking the world. My tools should enable the creation of pet projects, the curation of their code, and the insurance of their completion, regardless of the language.

More than on personal projects, though, I spend time transforming the code others have written. This is the bulk of the code I write as my day job, transformations of existing code that is not my own and that I may not yet have the full understanding of. My editor should enable and embrace refactoring and extending existing code. It should make introspecting and exploring code bases easy and intuitive.

My projects are all version controlled using Git. Exploring the history of a project, gaining points of reference within codebases, these are core parts of my learning model in a new code base; who owns what, and how do they think? My tools should make it easy to answer these questions, and should allow me to manipulate the repository myself, be that rewriting history, or simply committing new code.

(provide 'cce-code-core)

Core Programming Environment Setup

There is some base-level tooling required for me to get my job done as a programmer, let's install those tools here:

- name: git installed
    state: installed
    name: git
  when: ansible_pkg_mgr == "apt"

- name: git installed
    state: installed
    name: git
  when: ansible_pkg_mgr == "dnf"

I only use line numbering when I'm programming, let's turn it on! I turn off eager loading and delay the rendering of this because for big files, because it can get really damn slow.

(setq linum-delay t
      linum-eager nil)
(add-hook 'prog-mode-hook 'linum-mode)

Semantic Mode is a neat built-in code parser with autocomplete, refactor and other cool bits.

(add-hook 'prog-mode-hook 'semantic-mode)

Install some one-off modes that auto-enable when we need them and need no configuration.

(install-pkgs '(jinja2-mode

Aggressive Indent makes sure your code is always properly indented. Paired with DTRT, we end up with the ability to never actually have to care about our code indentation, as it should be.

(install-pkgs '(aggressive-indent))
(eval-after-load 'aggressive-indent-mode (lambda ()
                                           (diminish 'aggressive-indent-mode "⮕")))

(defun rrix/re-indent ()
  (unless (or (eq major-mode
              (eq major-mode
    (local-set-key (kbd "RET") 'reindent-then-newline-and-indent)))
(add-hook 'prog-mode-hook 'rrix/re-indent)

Code exploration

Code Surfing

Code Surf is something that I've wanted to experiment with for a while; basically, we want to be able to follow code similar to how I use in my highlight-symbol hydra. It puts a focus on the data flow of the function that you're looking at.

(defun enable-code-surf ()

  (set-face-attribute 'font-lock-builtin-face nil :inherit 'default :foreground nil :background nil)
  (set-face-attribute 'font-lock-comment-face nil :inherit 'default :foreground "grey50" :background nil)
  (set-face-attribute 'font-lock-comment-delimiter-face nil :inherit 'font-lock-comment-face)
  (set-face-attribute 'font-lock-constant-face nil :inherit 'default :foreground nil :background nil)
  (set-face-attribute 'font-lock-doc-face nil :inherit 'default :foreground "grey50" :background nil)
  (set-face-attribute 'font-lock-function-name-face nil :inherit 'default :foreground nil :background nil)
  (set-face-attribute 'font-lock-keyword-face     nil :inherit 'default :foreground nil :background nil :weight 'normal)
  (set-face-attribute 'font-lock-negation-char-face nil :inherit 'default) :foreground nil :background nil
  (set-face-attribute 'font-lock-preprocessor-face nil :inherit 'default) :foreground nil :background nil
  (set-face-attribute 'font-lock-string-face nil :inherit 'default :foreground nil :background nil)
  (set-face-attribute 'font-lock-type-face nil :inherit 'default :foreground nil :background nil)
  (set-face-attribute 'font-lock-variable-name-face nil :inherit 'default :foreground nil :background nil)
  (set-face-attribute 'font-lock-warning-face      nil :inherit 'default :foreground nil :background nil)
  (set-face-attribute 'font-lock-regexp-grouping-backslash nil :inherit 'default :foreground nil :background nil)
  (set-face-attribute 'font-lock-regexp-grouping-construct nil :inherit 'default :foreground nil :background nil)

  (setq rainbow-identifiers-faces-to-override '(font-lock-function-name-face

(setq code-surf-last-themes custom-enabled-themes)
(define-minor-mode code-surf-mode "Disable most font locking and enable rainbow-delimeters"
  nil "[CS]" nil
  (if code-surf-mode
      (message "enable")
      (message "disable")
      (global-rainbow-identifiers-mode -1)
      (global-auto-highlight-symbol-mode -1)
      (mapc (lambda (name)
              (enable-theme name))

(define-global-minor-mode global-rainbow-identifiers-mode rainbow-identifiers-mode (lambda ()
                                                                                     (when (derived-mode-p 'prog-mode)

(install-pkgs '(rainbow-identifiers))

(setq rainbow-identifiers-cie-l*a*b*-lightness 40
      rainbow-identifiers-cie-l*a*b*-saturation 70
      rainbow-identifiers-choose-face-function 'rainbow-identifiers-cie-l*a*b*-choose-face)


Projectile1 is one of those tools like Helm that some people will say is too heavy or big or bloated, but is incredibly well designed and full featured.

(require 'projectile)
(add-hook 'prog-mode-hook 'projectile-mode)
(diminish 'projectile-mode)

Projectile has some pretty nice functionality, which we expose via this Hydra, prefixed on C-x p, as a override to projectile's default C-x p prefix.

From here we can dive in to a live grep with a, find files with h, switch project using P, and other random crap.

(defhydra hydra-projectile-other-window (:color teal)
  ("f"  projectile-find-file-other-window        "file")
  ("g"  projectile-find-file-dwim-other-window   "file dwim")
  ("d"  projectile-find-dir-other-window         "dir")
  ("b"  projectile-switch-to-buffer-other-window "buffer")
  ("q"  nil                                      "cancel" :color blue))

(defhydra hydra-projectile (global-map "C-x p" :color teal)
     PROJECTILE: %(projectile-project-root)

     Find File            Search/Tags          Buffers                Cache
                      _a_: grep              _i_: Ibuffer           _c_: cache clear
                                           _b_: switch to buffer  _x_: remove known project
                      _o_: multi-occur       _K_: Kill all buffers  _X_: cleanup non-existing
  _r_: recent file                                               ^^^^_z_: cache current
  _d_: dir

  ("a"   projectile-grep)
  ("b"   projectile-switch-to-buffer)
  ("c"   projectile-invalidate-cache)
  ("d"   projectile-find-dir)
  ("f"   projectile-find-file)
  ("i"   projectile-ibuffer)
  ("j"   counsel-imenu)
  ("K"   projectile-kill-buffers)
  ("m"   projectile-multi-occur)
  ("o"   multi-occur)
  ("P"   projectile-switch-project "switch project")
  ("p"   projectile-switch-project)
  ("s"   projectile-switch-project)
  ("r"   projectile-recentf)
  ("x"   projectile-remove-known-project)
  ("X"   projectile-cleanup-known-projects)
  ("z"   projectile-cache-current-file)
  ("`"   hydra-projectile-other-window/body "other window")
  ("q"   nil "cancel" :color blue))

Ubiquitous Version Control

Magit and VC are both a part of my toolchain, through this hydra that I use. They're both incredibly powerful tools, serving slightly different use cases.

I have a hydra that acts as an entry point for my Version Control workflow.

(install-pkgs '(magit))
(require 'magit)
(defhydra hydra-magit (global-map "C-c g" :color teal :hint nil)
     PROJECTILE: %(projectile-project-root)

     Immuting            Mutating
  _w_: blame line      _b_: checkout
  _a_: annotate file   _B_: branch mgr
  _d_: diff            _c_: commit
  _s_: status          _e_: rebase
  _l_: log
  _t_: time machine

  ("w" git-messenger:popup-message)
  ("a" vc-annotate)
  ("b" magit-checkout)
  ("B" magit-branch-manager)
  ("c" vc-next-action)
  ("d" magit-diff-working-tree)
  ("e" magit-interactive-rebase)
  ("s" magit-status)
  ("l" magit-log)
  ("t" git-timemachine))

Git Blame

I have Git blame on C-x g ! using git-messenger 2, a neat little piece of kit which gives you a popup notification with the commit details of the current line of code.

(install-pkgs '(git-messenger))
(require 'git-messenger)

NEXT Branching

Phabricator/Arcanist basically requires you to always be working in a branch. If you want to open a diff, you open a diff between two branches, your work branch and master, so you have to be working on a branch. I need an easy way to keep me from commit on master in certain repositories, maybe as a pre-commit hook as a starter, but it should probably end up being a part of my editor workflow.

In the mean time, I can switch branches using a combination of Magit and Hydra, on C-x g b and C-x g B to open the branch manager.


I have two ways of doing this, in general; larger commits and single-file changes.

The latter I can use vc-next-action to do in a single blast, but for larger blobs of code, or to stage single hunks in a file, I'll need to use magit-status, add the files and then commit them all.

I have vc-next-action bound to C-x g c and I have magit-status bound to C-x g s.

History rewriting

The workflow that I use at work encourages clean git history, by doing rebases during landing; this lets me rewrite history as I please while I am working and bundle each piece of work in to a single commit or set of commits. This is bound to C-x g e.

History viewing

Magit has good repository logging, and git-timemachine3 can walk an individual file's history really well. I have magit-log bound to C-x g l and I have git-timemachine bound to C-x g t.

(install-pkgs '(git-timemachine))
(require 'git-timemachine)


I don't do this enough to put it on a dedicated global key, it is available inside of magit-status under z, let's leave it there.

Autocomplete with Company

(install-pkgs '(company))

I use company for more than just programming completions (see 💕=company-emoji=💕, f.e.), so let's just enable it everywhere.

(global-set-key (kbd "C-TAB") 'company-complete)

NEXT Refactoring Tools

NEXT Phabricator/Arcanist integration

NEXT Create some nice Phabricator reports to make Triage easier

NEXT Phabricator org-mode integration

  • pull tdown in to an org-mode document
  • updates as necessary


Author: Ryan Rix

Created: 2019-03-14 Thu 23:09

Validate XHTML 1.0