     (comp vec #(take limit (drop offset %)) order-fn)))
 
 (defn format-value [v]
-  (if (set? v)
-    (let [xs (for [x v] (if (keyword? x)
-                          (str "#" (name x) " ")
-                          (str x " ")))]
-      (.trim (apply str xs)))
-    v))
-
-(defn make-entry-formatter [opt-map]
+  (if (not (set? v))
+    v
+    (let [xs (for [x v]
+               (if (keyword? x)
+                 (str "#" (name x) " ")
+                 (str x " ")))]
+      (.trim (apply str xs)))))
+
+(defn- mk-kv-formatter [d]
+  (cond
+   (or
+    (nil? d)
+    (= "kv" d)) #(str (name (get % 0)) ": " (format-value (get % 1)))
+    (= "k" d)   #(str (name (get % 0)))
+    (= "v" d)   #(format-value (get % 1))))
+
+(defn- line [kv-formatter kv-pair]
+    (str (apply str (kv-formatter kv-pair) "\n")))
+
+(defn mk-entry-formatter [opt-map]
   (if (:clj opt-map)
     identity
-    (let [make-line (fn [kv-formatter kv-pair]
-                      (str (apply str (kv-formatter kv-pair) "\n"))),
-          d (:display opt-map),
-          kv-formatter
-          (cond
-           (or
-            (nil? d)
-            (= "kv" d)) #(str (name (get % 0)) ": " (format-value (get % 1)))
-            (= "k" d)   #(str (name (get % 0)))
-            (= "v" d)   #(format-value (get % 1)))]
+    (let [kv-formatter (mk-kv-formatter (:display opt-map))]
       (fn [entry]
-        (apply str (for [kv-pair entry] (make-line kv-formatter kv-pair)))))))
-
-(defn make-selector [opt-map]
+        (apply str (for [kv-pair entry] (line kv-formatter kv-pair)))))))
+
+(defn mk-selector [opt-map]
   (if (:all opt-map)
     identity
     #(select-keys % (reverse (:select opt-map)))))
 
-(defn make-filter [opt-map]
+
+;; helper fns for mk-filter
+
+(defn- mk-all-text-tokens? [f-txts]
+  (fn [entry]
+    (or (empty? f-txts)
+        (let [text (:text entry)]
+          (apply l-and (map (partial supstring-of? text) f-txts))))))
+
+(defn- mk-all-tags? [f-tags]
+  (fn [entry]
+    (or (empty? f-tags)
+        (let [tags (:tags entry)]
+          (apply l-and (map (partial contains? tags) f-tags))))))
+
+(defn- mk-key-matches-filtered? [k op filtered]
+  (fn [entry]
+    (or (empty? filtered)
+        (let [xs (k entry)]
+          (apply op (map (partial contains? xs) filtered))))))
+
+;; TODO
+
+(defn- mk-all-kvs? [f-kvs]
+  (fn [entry]
+    (or (empty? f-kvs)
+        (apply
+         l-and
+         (for [e f-kvs]
+           (let [kv      (first e)
+                 test-k  (get kv 0)
+                 test-v  (get kv 1)
+                 entry-v (test-k entry)]
+             (cond
+              ;; special case for "key=" (w/o value)
+              (= :any test-v) (not (nil? entry-v)), ;; then that suffices
+              (can-as-number? test-v) (and (can-as-number? entry-v)
+                                           (= (as-number test-v) (as-number entry-v))),
+              :else (substring-of? test-v entry-v))))))))
+  
+;; filter
+
+(defn mk-filter [opt-map]
   (let [xs (:filter opt-map)]
     (if (empty? xs)
       identity
-      (let [f-txts (filter string? xs),
-            f-tags (filter keyword? xs),
-            f-kvs  (filter map? xs),
-            all-text-tokens
-            (fn [entry]
-              (or (empty? f-txts)
-                  (let [text (:text entry)]
-                    (apply l-and (map (partial supstring-of? text) f-txts))))),
-            all-tags
-            (fn [entry]
-              (or (empty? f-tags)
-                  (let [tags (:tags entry)]
-                    (apply l-and (map (partial contains? tags) f-tags))))),
-            all-kvs
-            (fn [entry]
-              (or (empty? f-kvs)
-                  (apply l-and
-                         (for [e f-kvs]
-                           (let [kv      (first e)
-                                 test-k  (get kv 0)
-                                 test-v  (get kv 1)
-                                 entry-v (test-k entry)]
-                             (cond
-                              ;; special case for "key=" (w/o value)
-                              (= :any test-v) (not (nil? entry-v)) ;; then that suffices
-                              (can-as-number? test-v) (and (can-as-number? entry-v)
-                                                           (= (as-number test-v) (as-number entry-v)))
-                              :else (substring-of? test-v entry-v)))))))]
-            (fn [entry] (and (all-text-tokens entry)
-                             (all-tags entry)
-                             (all-kvs entry)))))))
-
+      (fn [entry] (and ((mk-all-text-tokens? (filter string? xs)) entry)
+                       ((mk-all-tags? (filter keyword? xs)) entry)
+                       ((mk-all-kvs? (filter map? xs)) entry))))))
+
+      ;; (fn [entry]
+      ;;   (reduce
+      ;;    l-and
+      ;;    (for [pred [(mk-key-matches-filtered? :text l-and (filter string? xs))
+      ;;                (mk-key-matches-filtered? :tags l-and (filter keyword? xs))
+      ;;                (mk-all-kvs? (filter map? xs))]]
+      ;;      (pred entry)))))))
+          
 
 ;;; non-io parts of file access functions
 

;; created 2012-01-14 00:10
;; author Harald Beck

(ns ueberfoo.commandline

  (let [xs          (:entries (file-load-ueberfoo filename))
        options-vec (make-options-vec options)
        opt-map     (parse-list-options options-vec)
        filtered    (filter (mk-filter opt-map) xs)
        selected    (map (mk-selector opt-map) filtered)
        opt-map-n   (assoc opt-map :nr-of-entries (count selected))
        result      ((mk-list-post-processor opt-map-n) selected)
        xform       (mk-entry-formatter opt-map)
        one-liners? (and (not (:all opt-map)) (= 1 (count (:select opt-map))))
        printer     (if one-liners? print println)]
    (do
