Files
clojure-tui/examples/list_selection.clj
2026-01-21 01:21:05 -05:00

93 lines
2.8 KiB
Clojure

(ns examples.list-selection
"List selection example - demonstrates cursor navigation and multi-select.
Mirrors bubbletea's list examples."
(:require [tui.core :as tui]
[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-model [{:keys [cursor items] :as model} msg]
(cond
;; Quit
(or (tui/key= msg "q")
(tui/key= msg [:ctrl \c]))
[model tui/quit]
;; Move up
(or (tui/key= msg :up)
(tui/key= msg "k"))
[(update model :cursor #(max 0 (dec %))) nil]
;; Move down
(or (tui/key= msg :down)
(tui/key= msg "j"))
[(update model :cursor #(min (dec (count items)) (inc %))) nil]
;; Toggle selection
(tui/key= msg " ")
[(update model :selected
#(if (contains? % cursor)
(disj % cursor)
(conj % cursor)))
nil]
;; Submit
(tui/key= msg :enter)
[(assoc model :submitted true) tui/quit]
:else
[model nil]))
;; === 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-model
:view view})]
(when submitted
(println)
(println "Your order:")
(doseq [idx (sort selected)]
(println " -" (nth items idx))))))