 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (defun jail-windows/register-layout (layout-name layout-def)
-  "Register a new layout
-
-TODO: Describe layout
-
-Remember that 'unassigned is a special group name and can't be directly
-assigned."
-  (jail-windows/unregister-layout layout-name)
-  (push (cons layout-name layout-def)
-        jail-windows--registered-layouts))
+  "Register a new jail-windows layout
+
+LAYOUT-NAME should be a symbol to briefly describe the layout.
+
+LAYOUT-DEF should be an alist containing elements with the following cells:
+
+ (description . \"...\")
+     A human-readable description of the layout, its purpose, inspiration, or
+     any other relevant information. This cons cell is not used by the code.
+
+ (group-defs (group1 (\"...\"
+                      (lambda () ...)
+                      t)))
+     An alist of group names to lists of group matchers. Group matchers can be
+     one of several types: strings are treated as regexps that will test
+     against buffer names; functions are treated as predicates to test against
+     the buffer object; the symbol t matches all buffers.
+
+     Group defs will be evaluated in the order that they are specified in the
+     layout definition. In other words, when multiple groups contain a matcher
+     that would return t, the top group will be assigned the window.
+
+     Note that group-defs may include an element with car of symbol unassigned.
+     This is a special group reserved for windows that were not explicitly
+     assigned to any other group in the window-layout (as described below.)
+     This 'unassigned group may not have any windows explicitly assigned to it.
+
+ (window-layout (- (size . 5)
+                   (repeat . t))
+                (| (ratio . 0.5))
+                (* (groups . (a b c)))
+                (^))
+     A list describing the desired layout of windows within the frame. Each
+     item of the list is a cons cell with car describing the type of layout
+     action, and cdr as an alist of options for the specified action.
+
+     The actions are performed sequentially when the layout is built. The
+     actions available are as follows:
+
+       symbol `-' -- Split the window vertically down
+       symbol `|' -- Split the window horizontally to the right
+       symbol `*' -- Set options on the current window
+       symbol `^' -- Refer to the window created by previous action
+
+     Note that options specified for each split will be set on the source of
+     the split; in other words, options on symbol `-' will be set on the upper
+     window, leaving the selected window as the bottom window.
+
+ (post-build . (fun1 fun2))
+     A list of functions to call after building the layout.
+     TODO(rgrimm): Test this more
+
+For examples of the structure, refer to built-in layouts such as
+`jail-windows--builtin-layout:code'."
+  (let ((previous-layout (assq layout-name jail-windows--registered-layouts)))
+    (if previous-layout
+        (progn (setcdr previous-layout layout-def)
+               jail-windows--registered-layouts)
+      (push (cons layout-name layout-def)
+            jail-windows--registered-layouts))))
 
 (defun jail-windows/unregister-layout (layout-name)
   "Unregister a layout"

                                         (-map #'car window-groups)))))
        (jail-windows--set-option nil
                                  'groups
                                  (--map `(,(cons 'name it)
                                           ,(cons 'matchers
                                                  (cdr (assq it
                                                             .group-defs)))
                                           ,(cons 'windows
                                                  (cdr (assq it
                                                             window-groups))))
                                         group-names)))

      ;; Try to show all buffers that were previously showing
      (--each prev-active-buffers
        (setq selected-window
              (jail-windows--find-window-for-buffer nil
                                                    it
                                                    '()
                                                    used-windows))
        (when selected-window
          (push selected-window used-windows)
          (select-window selected-window 'norecord)
          (switch-to-buffer it 'norecord 'force-same-window)))

      ;; Try to select the previously selected buffer; otherwise select the
      ;; first window in the frame
      (select-window (or (get-buffer-window prev-selected-buffer
                                            (selected-frame))
                         (frame-first-window))
                     'norecord)))
  (jail-windows--update-modeline t))

;;;###autoload

ACTIVATE-MODE is non-nil, this function will activate jail-windows-mode on the
selected frame."
  (interactive (list (jail-windows--prompt-for-layout "Layout to activate: ")
                     (unless (jail-windows--frame-active-p)
                       (yes-or-no-p
                        "Activate jail-windows-mode in this frame? "))))
  (unless (jail-windows/layout-p layout-name)
