Contributing to Spacemacs

Recently I touched a Rails/JavaScript codebase and I needed to tweak my Spacemacs a little. The defaults are great, but I felt that some things were missing: better integration with Rubocop and a REPL for JS. So, instead of making it a private layer, why not contribute back to the project? It’s easier than you think!

Places to start: Spacemacs guidelines for contributors and this great tutorial by Tristan Hume.

Considering you followed the official installation instructions:

git clone --recursive https://github.com/syl20bnr/spacemacs ~/.emacs.d

You should:

  • Fork the original repo in Github
  • Add your repository as a remote

    If you are using Magit (and you should), press ‘M a’ to add your repo. Magit will prompt for the remote name (I chose ‘my-fork’) and URL.

  • Branch from the ‘develop’ branch

    I usually end up with two branches - one that I merge with my own version of master (so that I can use it with the stable version of Spacemacs) and another for PR’ing in the official Spacemacs repository (the ‘develop’ branch).

  • Make your changes and commit them

    Spacemacs’ policy is that PRs must contain only ONE commit. No worries - develop with as many commits as you want, and let Magit do the hard work for you by rebasing your branch with the ‘squash’ option. This also works if you need to make changes during code review - just squash your new commits and push them to your remote repository (git will probably complain about the remote tip being behind your branch, but it’s usually safe to ignore this).

  • Push the changes to your remote repository and then make a pull request to the original Spacemacs repository

    Remember, all pull requests should be against the ‘develop’ branch, NOT master!

If during this process your branch gets behind the current develop (Spacemacs is a very active project, and as of the time of this writing this happened with me), just press ‘F -r o origin/develop’ in Magit, which translates to

git pull --rebase origin/develop

That’s it, you contributed to Spacemacs and made it one step closer to the best out-of-the-box Emacs experience there is.

And if you are a JS developer, check out skewer-mode’s demo video, it’s awesome!

Vi keybindings in terminal and ansi-term

I did not see this problem described somewhere else, so this is a small post to document it. I was having an issue similar to the one described in this blog post, but ansi-term could print the “weird” characters that were supposed to cause the problem. After checking my dotfiles a bit, I found this piece of code:

# vi keybindings for zsh
bindkey -v
zle-keymap-select () {
    if [ $TERM = "screen" ]; then
        if [ $KEYMAP = vicmd ]; then
            echo -ne '\033P\033]12;#ff6565\007\033\\'
        else
            echo -ne '\033P\033]12;grey\007\033\\'
        fi
    elif [ $TERM != "linux" ]; then
        if [ $KEYMAP = vicmd ]; then
            echo -ne "\033]12;#ff6565\007"
        else
            echo -ne "\033]12;grey\007"
        fi
    fi
}; zle -N zle-keymap-select
zle-line-init () {
    zle -K viins
    if [ $TERM = "screen" ]; then
        echo -ne '\033P\033]12;grey\007\033\\'
    elif [ $TERM != "linux" ]; then
        echo -ne "\033]12;grey\007"
    fi
    zle vi-cmd-mode
}; zle -N zle-line-init

This piece sets up a red cursor for when I am in ‘vim mode’ in zsh. Apparently Emacs did not recognize these escape sequences and generated this weird output:

weird ansi-term behavior

ansi-term sets up an env variable called $EMACS, so I just wrapped this code around it:

if [ -n "$EMACS" ]; then
    echo "no vi keybindings inside emacs terms"
else
    # the previous giant ball of code is now here
fi

And it works correctly now:

yay for working ansi-term

Migrating an Android build system to Gradle

At my current employer, our team recently underwent a migration of our Android app’s build system to Gradle, now the official choice for Android Studio. Following is a summary of the good and bad things in this change.

The good

Automatic dependency management

This feature is what made us consider switching in the first place. Even though we don’t use many external dependencies, including 3rd-party libraries for our project was like this:

  • find the project’s source code on Github and download it
  • if it builds and runs correctly in Android Studio, set it as a git submodule of our project
  • integrate it with Apache Ant, our old build system
  • debug and fix any problems Jenkins might have with the new setup

This is far from ideal. In contrast, Gradle got us covered with one line of code:

compile 'your.library.name:major.minor.patch'

Want to package some subdirectories as subprojects? Just add a build.gradle to each of these subdirectories, include them as projects in your main build.gradle and you are set. This encourages modularity and code reuse, always a Good Thing®.

Support for multiple app versions - debug/release, free/paid…

This is the other “killer feature” of Gradle. It is very easy to make different build profiles for an app, each with its own set of source files, compile options, feature toggles and many more. I find it particularly satisfying to know I can stuff my debug builds with instrumentation code and libraries for inspection, and when releasing, no space or processing time will be used.

Other benefits

In the first place, it is very refreshing to use an actual programming language (Groovy) instead of XML. Easier to understand and write, and much better for newcomers not used to Ant (like me - I had to look up documentation every time I wanted to tweak our old build system). This also lowers the barrier of adoption for potential project contributors.

Gradle also introduced the ability to inject constants in the BuildConfig classes of the project. This is particularly useful when injecting API URLs and access configurations (e.g.: extra header codes) in your application. Nothing world-changing, but very welcome.

Did you know that Gradle integration with Ant is excellent, even featuring a one-liner for importing build.xml?

ant.importBuild 'build.xml'

The bad

Android Studio integration issues

Android Studio integration with Gradle is good - if you start a project following its conventions. In our case, we migrated an Eclipse/Ant application, using non-standard paths, which led to unexpected behavior in the IDE. Some team members even reported finding “won’t fix” bugs with non-standard paths.

The GUI for build configuration is very simple, and sometimes it rewrote our build.gradle badly. I recommend always writing it by hand if possible.

Build times

tl, dr: always enable the Gradle daemon. If you only use Android Studio, it’s on by default; if you are using Gradle in the command-line, run this command:

touch ~/.gradle/gradle.properties && echo "org.gradle.daemon=true" >> ~/.gradle/gradle.properties

In my machine, I see an improvement of a few seconds in build times. Which is great, because personally, I find the edit-compile-run cycle in Android slow…but it may only be my appreciation for REPLs talking. Unfortunately, there are none for Android because of technical limitations, but there are plugins that come close and smart workarounds.

Conclusion

There are many benefits and very few drawbacks to using Gradle as a build system (and in my experience, these are mostly related to IDE integration, not issues with Gradle per se). So, if you are in a JVM environment, give it a go! It works for most Java projects, not only Android ones, and there are many plugins to help you achieve what you want, so try it already!

Ensure working trees are empty before running 'git push'

Every developer has been through this scenario:

  • make changes, bug seems fixed
  • commits everything
  • refactors some bits of code
  • pushes code to the remote

and everything seems fine and dandy…until Jenkins warns that you broke the build because some changes you made were in a different repository that you forgot to update.

I’ve been through that too, but fortunately with Gradle you have an easy way to avoid this. Put this in your Gradle init script (for unix-y systems, it’s ~/.gradle/init.gradle):

allprojects {
    task paths << { task -> println "$task.project.projectDir" }
}

And put this script somewhere (I usually put this in ~/bin):

#!/bin/bash

# This script checks if the staging area for git directories in $1/stdin is empty
while read line; do
    dir=$line
    curdir=$PWD
    cd $dir
    gitroot=`git rev-parse --show-toplevel`
    cd $gitroot
    if [[ -z "$gitroot" ]]
    then
        echo "No git directory @ $dir!"
        cd $curdir
        exit 1
    fi
    changed=`git status -s | grep -v "^??"`
    if [[ -z "$changed" ]]
    then
        cd $curdir
    else
        cd $curdir
        printf "There are changed files in $dir:\n$changed"
        exit 1
    fi
done < "${1:-/dev/stdin}"

And add this to your pre-push hook:

echo "Checking for unstaged changes in project directories"
gradle -q path | ~/bin/git-check-empty-staging-area.sh
if [ $? -ne 0 ]
then
    exit 1
fi

Of course, you can also use whatever command outputs a list of git directories instead of ‘gradle -q path’.

Feel free to update the gist with better code, and let me know!

Fix for :reg error in Evil

Small post with a fix for a (somewhat) common problem. If you use Emacs’ registers to save window or frame configurations, you probably found a small bug with the ‘:reg’ command in Evil-mode.

Backtrace with 'wrong-type-argument number-or-marker-p _' error

Fortunately, the solution is very simple, just apply this patch and it will work. Or you can just copy-paste and evaluate this code:

(defun evil-register-list ()
  "Returns an alist of all registers"
  (sort (append (mapcar #'(lambda (reg)
                            (cons reg (evil-get-register reg t)))
                        '(?\" ?* ?+ ?% ?# ?/ ?: ?. ?-
                              ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9))
                (delq nil (mapcar (lambda (reg) (and (number-or-marker-p (car reg)) reg)) register-alist)) nil
                nil)
        #'(lambda (reg1 reg2) (< (car reg1) (car reg2)))))