(ns examples.list-selection "List selection example - demonstrates cursor navigation and multi-select. Mirrors bubbletea's list examples." (:require [tui.core :as tui] [tui.events :as ev] [clojure.string :as str])) ;; === Model === (def initial-model {:cursor 0 :items ["Pizza" "Sushi" "Tacos" "Burger" "Pasta" "Salad" "Soup" "Steak"] :selected #{} :submitted false}) ;; === Update === (defn update-fn [{:keys [model event]}] (let [{:keys [cursor items]} model] (cond ;; Quit (or (ev/key= event \q) (ev/key= event \c #{:ctrl})) {:model model :events [(ev/quit)]} ;; Move up (or (ev/key= event :up) (ev/key= event \k)) {:model (update model :cursor #(max 0 (dec %)))} ;; Move down (or (ev/key= event :down) (ev/key= event \j)) {:model (update model :cursor #(min (dec (count items)) (inc %)))} ;; Toggle selection (ev/key= event \space) {:model (update model :selected #(if (contains? % cursor) (disj % cursor) (conj % cursor)))} ;; Submit (ev/key= event :enter) {:model (assoc model :submitted true) :events [(ev/quit)]} :else {:model model}))) ;; === View === (defn view [{:keys [cursor items selected submitted]}] (if submitted [:col [:text {:bold true :fg :green} "You selected:"] [:text ""] (if (empty? selected) [:text {:fg :gray} "(nothing selected)"] [:col (for [idx (sort selected)] [:text (str " - " (nth items idx))])])] [:col {:gap 1} [:box {:border :rounded :padding [0 1] :title "What's for lunch?"} [:col (for [[idx item] (map-indexed vector items)] (let [is-cursor (= idx cursor) is-selected (contains? selected idx)] [:row {:gap 1} [:text {:fg (when is-cursor :cyan)} (if is-cursor ">" " ")] [:text (if is-selected "[x]" "[ ]")] [:text {:bold is-cursor :fg (cond is-selected :green is-cursor :cyan :else :default)} item]]))]] [:row {:gap 2} [:text {:fg :gray} "j/k: move"] [:text {:fg :gray} "space: select"] [:text {:fg :gray} "enter: confirm"] [:text {:fg :gray} "q: quit"]] [:text {:fg :cyan} (str (count selected) " item" (when (not= 1 (count selected)) "s") " selected")]])) ;; === Main === (defn -main [& _args] (println "Starting list selection...") (let [{:keys [items selected submitted]} (tui/run {:init initial-model :update update-fn :view view})] (when submitted (println) (println "Your order:") (doseq [idx (sort selected)] (println " -" (nth items idx))))))