         [overtone.util lib doc]))
 
 (defn- map-terms-to-regexps
+  "convert a list of patterns/objects to a list of patterns by not modifying
+  the regex patterns and converting other objects to strings and the strings
+  to regex patterns. Typically the other obects will be standard strings."
   [terms]
   (map (fn [term]
          (if (= java.util.regex.Pattern (type term))

           (re-pattern (str term))))
       terms))

(defn find-ugen-specs
  [terms]
  (let [regexps (map-terms-to-regexps terms)]
    (sort-by

                      (= matches regexps)))
                  (seq UGEN-SPECS))))))

(defn- print-ug-summaries
  "Pretty print out a list of ugen specs by printing their name and summary on
  separate lines."
  [specs longest-name-len]
  (dorun
   (map
    (fn [spec]
      (let [n (str (overtone-ugen-name (:name spec)))
            n (gen-padding n (+ 2 (- longest-name-len (.length n))) " ")
            s (indented-str-block
               (get spec :summary "") DOC-WIDTH (+ 4 longest-name-len))]
        (println (str n "  " s))))

    specs)))

(defn- print-ug-docs
  "Pretty print out a list of ugen specs by printing out their names and
  full-doc strings."
  [specs]
  (dorun
   (map
    #(println (str "  "
                   (overtone-ugen-name (:name %))
                   "\n"
                   (:full-doc %)
                   "\n\n  -------------"))
    specs)))

(defn find-ug
  "Find a ugen containing the specified terms which may be either strings or
  regexp patterns. Will search the ugen's docstrings for occurrances of all the
  specified terms. Prints out a list of summaries of each matching ugen

  (find-ug \"foo\")         ;=> finds all ugens containing the word foo
  (find-ug \"foo\" \"bar\") ;=> finds all ugens containing the words foo AND bar
  (find-ug #\"foo*\")       ;=> finds all ugens matching the regex foo*"
  [& search-terms]
  (let [specs            (find-matching-ugen-specs search-terms)
        names            (map #(overtone-ugen-name (:name %)) specs)
        longest-name-len (length-of-longest-string names)]
    (if (empty? specs)
      (println "Sorry, unable to find a matching ugen.")
      (print-ug-summaries longest-name-len))))

(defn find-ug-doc
  "Find a ugen containing the specified terms which may be either strings or
  regexp patterns. Will search the ugen's docstrings for occurrances of all the
  specified terms. Prints out each ugens full docstring. Similar to find-doc.

  (find-ug-doc \"foo\")         ;=> finds all ugens containing the word foo
  (find-ug-doc \"foo\" \"bar\") ;=> finds all ugens containing the words foo
                                    AND bar
  (find-ug-doc #\"foo*\")       ;=> finds all ugens matching the regex foo*"
  [& search-terms]
  (let [specs (find-matching-ugen-specs search-terms)]
    (if (empty? specs)
      (println "Sorry, unable to find a matching ugen.")
      (print-ug-docs specs))))
