 (defn so-widget []
   (if @so-archives-available
     [:div
-     [:p "Suggested tags:"]
+     [:p "Suggested tags (select ones you want in your index):"]
      [:ul
       (doall (for [tag suggested-tags]
-               (if (nil? @so-grep-progress)
-                 (if (not @so-indexing)
-                   (do ^{:key (str "so_tags_" tag)}
-                       [:li (str tag " | ")
-                        [:a
-                         {:on-click #(start-so-grepping tag)}
-                         "generate index"]])
-                   (do
-                     ^{:key (str "so_tags_" tag)}
-                     [:li (str tag)]))
-                 (doall
-                   ^{:key (str "so_indexing_" tag)}
-                   [:li (str
-                          "Indexing " tag ": "
-                          (.toFixed
-                            (min 99.99                      ; never show 100%
-                                 (* 100 (/ @so-grep-progress
-                                           @so-archives-total)))
-                            2)
-                          "% filtering, "
-                          (or @so-index-progress 0)
-                          " indexing")]))))]]
+               (do ^{:key (str "so_tags_" tag)}
+                   [:li
+                    [:label
+                     [:input {:type     "checkbox"
+                              :checked  (get @so-index-tags tag)
+                              :disabled @so-indexing
+                              :on-change
+                                        (fn []
+                                          (if (nil? (get @so-index-tags tag))
+                                            (reset! so-index-tags
+                                                    (conj @so-index-tags tag))
+                                            (reset! so-index-tags
+                                                    (disj @so-index-tags tag))))}]
+                     [:span {:class "checkable"} tag]]]
+                   )))]
+     (if @so-indexing
+       [:p (str
+             "Indexing : "
+             (.toFixed
+               (* 100 (/ (or @so-grep-progress 0)
+                         (or @so-archives-total 1)))
+               2)
+             "% filtering, "
+             (or @so-index-progress 0)
+             " indexing")]
+       [:button {:on-click (fn []
+                             (reset! so-indexing true)
+                             (start-so-grepping))}
+        "Create index"])]
+
     [:div
      [:p "~8GB BitTorrent download required. (provided by archive.org)"]
      (if @so-downloading

           (reset! ended true)
           (check-all-done)))))

(defn start-so-grepping [tag]
  (let [mkdirp (.require js/window "mkdirp")
        path (.require js/window "path")]
    (.sync mkdirp (.join path (zest.docs.registry/get-so-root) tag))
    (go (let [comments-size (async/<! (archive-size "Comments"))
              posts-size (async/<! (archive-size "Posts"))
              child-process (.require js/window "child_process")
              Lazy (.require js/window "lazy")
              Buffer (.-Buffer (.require js/window "buffer"))
              sogrep (.spawn child-process "sogrep"
                             (array tag)
                             (js-obj "cwd"
                                     (.join path
                                            (zest.docs.registry/get-so-root))))
              p7zip-posts (open-so-archive "Posts" "x")]
          (reset! so-indexing true)
          (.pipe (.-stdout p7zip-posts)

        LuceneIndex
        (.-LuceneIndex (.require js/window "../build/Release/nodelucene"))
        idx (LuceneIndex. (.join path (zest.docs.registry/get-so-root)
                                 "new_index" "lucene"))

        done (atom 0)
        started (atom 0)
