                           (> x z) z
                           (< x a) a
                           :else x))
-            query ((get-in engines [0 :matcher]) text)
-            results ((get-in engines [0 :results]) query (config :thread-id))
+            results ((get-in engines [0]) text (config :thread-id))
             highlight-next!
             (fn []
               (om/update-state! owner :highlighted-result-index

            (fn []
              (clear-tags!)
              (highlight-clear!))
            autocomplete-open? (not (nil? query))]
          (dom/div #js {:className "message new"}
            (dom/textarea #js {:placeholder (config :placeholder)
                               :value (state :text)

    (not= -1 (.indexOf (normalize s) (normalize m)))))


; fn that returns results that will be shown if pattern matches
;    inputs:
;       text - current text of user's message
;       thread-id - id of the thread
;    output:
;       if a trigger pattern was matched, an array of maps, each containing:
;         :html - html to be displayed for the result
;         :action - fn to be triggered when result picked
;         (this array may be empty)
;       otherwise nil


(def engines
  [
   (fn [text thread-id]
     (when-let [query (second (re-matches #"(?:.|\n)*#(\S*)" text))]
       (let [thread-tag-ids (-> (store/id->thread thread-id)
                                :tag-ids
                                set)]
         ; suggest tags
         (->> (store/all-tags)
              (remove (fn [t]
                        (contains? thread-tag-ids (t :id))))
              (filter (fn [t]
                        (fuzzy-matches? (t :name) query)))))))])


; TODO: autocomplete mentions
(defn new-message-view [config owner]
  (reify
