Stop Procrastinating on Documentation

- 3 mins

Inspired by a recently-resurfaced blog post by Tom Preston-Werner, I’ve been looking for ways to avoid procrastinating on documentation.

The article stresses the importance of a good README to be written before - hence driven - your code, as it provides the basis upon which you think through your project and let others interface with your code.

The following pre-commit script appends a skeleton of your project’s structure to your README. Ideally this forces you to complete it by providing information on each directory’s content.

In order to use it, copy it under your .git/hooks and name it pre-commit. This will allow it to generate your structure before any commit. It will search for an already-existing incipit inside your README, so that it doesn’t make any copies.

If you prefer to run it once, then simply copy it under your project’s root and ruby pre-commit.

You can customize it by changing your SRC_ROOT, README_INCIPIT, or README_PATH.

View it on GitHub.

#!/usr/bin/env ruby

=begin
A hook to make sure that the README is updated with the current project's structure.
The scripts appends at the end of your project's README a markdown representation of 
your project. Now you have no excuses not to document your wonderful work!
Inspired by Readme Driven Development by Tom Preston-Werner (https://tom.preston-werner.com/2010/08/23/readme-driven-development.html)
Place it under .git/hooks and make sure that it is executable (chmod +x pre-commit).
=end

class ReadmeChecker
  SRC_ROOT = "/src".freeze
  README_INCIPIT = "# Project Structure".freeze
  README_PATH = Dir.pwd + "/README.md".freeze

  PASS_MSG = "pre-commit - SUCCESS - check passato".freeze
  NO_README_MSG = "pre-commit - ERROR - README not found".freeze
  NO_SRC_ROOT_MSG = "pre-commit - ERROR - src root not found".freeze

  class << self
    def perform
      check_files_exist

      unless File.readlines(README_PATH).grep(README_INCIPIT + "\n").any?
        File.write(README_PATH, README_INCIPIT + "\n\n", mode: "a+")

        explore(Dir.pwd + SRC_ROOT, 0)
      end
    end

    private

    def check_files_exist
      p NO_README_MSG and exit 0 unless File.exist?(Dir.pwd + "/README.md")
      p NO_SRC_ROOT_MSG and exit 0 unless File.exist?(Dir.pwd + SRC_ROOT)
    end

    def explore(path, depth)
      paths = Dir.glob(path + "/*")
      write_to_readme(path, depth)
      paths.each do |p|
        explore(p, depth + 1) if File.directory?(p)
      end
    end

    def write_to_readme(path, depth)
      to_write = "#" * (depth + 2) + " " + path[path.rindex("/") + 1..-1]

      File.write(README_PATH, to_write + "\n\n", mode: "a+")
    end
  end
end

ReadmeChecker.perform

Giulio Lodi

Giulio Lodi

Flutter RubyOnRails Rust. One espresso at a time.

rss facebook twitter github gitlab youtube mail spotify lastfm instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora quora