Bazaar Style Checker 0.1.1 released

I’m pleased to announce that Bazaar Style Checker 0.1.1 is now available. Get it at Launchpad. This is a bugfix release:

  • Handle paths with whitespace in style_checker_command. See the README file for details on configuration for this.
  • Workaround for annoying but harmless warning on Windows when trying to remove a temporary file.

Hopefully it won’t take too long before 0.2 is released with some new features. I’m planning to add support for a configuration file to be committed to the branch, similar to .bzrignore. If such a file (.bzrstylecheck) exists, that file will be used as configuration for that branch. If not the configuration locations valid in 0.1.x will be used. Not sure about the format of .bzrstylecheck yet, but I will add support for different commands depending on file type, something that’s not possible for the same branch with todays’ configuration.

Update: There seems to be a a draft for a specification suggesting that such configuration files should be put in a directory called .bzrmeta. Bazaar Style Checker will of course follow this convention.

Code style plugin for Bazaar

For some time ago I discovered this awesome code formatting tool called Uncrustify. I really believe that a consistent and aesthetic looking source code improves readability a lot. So after playing around with Uncrustify’s many settings and seeing how it could improve my code I wanted to integrate it tighter into my work flow. Since I use Bazaar as my main revision control system, it was natural to look at a Bazaar plugin. And of course, not only for using Uncrustify, but whatever source code beautifier you prefer.

So this is the first release of the Bazaar Style Checker Plugin, version 0.1.0. The main features included in this release are:

  • A commit-hook that checks if modified files violates a defined coding style.
  • The commit will fail or just print a warning if violations occur, based on your configuration.
  • An external program is used to check the code style. The command to run is configurable.
  • A new command “bzr style-check” to fix the code style for one file, only modified or for all files.
  • Simple backup routine for files that are fixed.

The way the plugin works is very simple. In order to check if a file violates the defined style, it simply runs the original file through the external program and compares the resulting beautified file with the original file. If there is a difference between the new and the original file, the conclusion is that there is at least one code style violation.

For more information on the features and how to configure the plugin, you should take a look at the README file.

To install the plugin, get the latest release and extract it your Bazaar plugins directory (e.g. “~/.bazaar/plugins”) or get the latest code from trunk:
bzr branch lp:bzr-style-checker stylechecker

For feature request and bug reports, please use Launchpad.

Indent with tabs, align with spaces

There have been countless discussions on whether you should use tabs or spaces to indent your code. Until recently I have been a fan of spaces. But why settle with spaces OR tabs? After some discussions with my good friend Ali some time ago, I agreed with myself that I actually prefer mixing tabs and spaces. The idea is of course to get the best of both worlds: indenting with tabs in order to respect each reader’s/developer’s preferred indentation width, and to align with spaces when expressions expand over multiple lines in order to ensure readability for different tab widths. The image below illustrates where I use tabs and where I uses spaces. This way the source code will stay readable even if it’s written with tabs of width 2 and read in an environment that has tabs width of 8.

Indent with tabs, align with spaces

I assume this is nothing new, and hopefully there is a lot of persons out there using this style. However, I was not able to find editors that can indent the code like this automatically nor any extensions to Emacs that does this. So I sat down and wrote a Lisp snippet in order to make Emacs automatically fill in spaces and tabs just the way I want it upon indentation. It uses functions from the c-mode to help to decide where to put spaces and tabs, so I hope it works for other formatting styles than just mine. (Sorry for the poor syntax highlighting, but there seems to be no support for lisp code.)

;; See http://www.gnu.org/software/emacs/manual/html_node/ccmode/Syntactic-Symbols.html
(defvar c-elements-to-align-with-spaces
  (list 'func-decl-cont
        'topmost-intro-cont
        'arglist-cont
        'arglist-cont-nonempty
        'statement-cont
        'c
        'inher-cont
        'member-init-cont
        'template-args-cont
        'objc-method-args-cont
        'objc-method-call-cont)
  "List of syntactic elements that should be aligned with spaces.
If you find an element you want to align with spaces but is not handled here,
find the syntactic element with C-c C-s or M-x c-show-syntactic-information
and simply add it to the list.")

(defun c-context-continuation-p (context)
  "Returns t if the given context is part of a continuation, i.e.
it should be aligned with spaces. The syntactic elements defined
as being a part of a continuation is defined by the variable
c-elements-to-align-with-spaces."
  (let ((continuation nil))
    (dolist (elem c-elements-to-align-with-spaces continuation)
      (when (assq elem context)
        (setq continuation t)))))

(defun c-indent-align-with-spaces-hook ()
  "If indent-tabs-mode is nil this function does nothing. If
indent-tabs-mode is enabled and if current indentation is an
alignment operation, this function will format the line so that
tabs are used until the indent level of the previous line and use
spaces for the rest (the aligment)."
  (interactive)
  (when indent-tabs-mode
    (let ((context c-syntactic-context)
          (curr-indent (current-indentation))
          (base-indent nil))
      (when (c-context-continuation-p context)
        (save-excursion
          ;; Find indentation of nearest not-continuation context
          (do ()
              ((not (c-context-continuation-p context)))
            (goto-char (c-langelem-pos (car context)))
            (setq context (c-guess-basic-syntax)))
          (setq base-indent (current-indentation)))
        ;; Untabify region between base indent and current indent
        (let ((end (point)))
          (save-excursion
            (while (> (current-column) base-indent)
              (backward-char))
            (untabify (point) end)))
        ;; We might need to adjust the marker to a more correct/practical
        ;; position.
        (when (= (current-column) base-indent)
          (back-to-indentation))))))

;; Activate the new indentation style
(setq c-special-indent-hook nil)
(add-hook 'c-special-indent-hook 'c-indent-align-with-spaces-hook)