Skip to content

Latest commit

 

History

History
200 lines (149 loc) · 4.7 KB

list.md

File metadata and controls

200 lines (149 loc) · 4.7 KB

List

Scrollable list component with keyboard navigation and item selection.

Quick Example

(require '[charm.components.list :as item-list])

(def my-list (item-list/item-list ["Apple" "Banana" "Cherry"]))

;; In update function
(let [[list cmd] (item-list/list-update my-list msg)]
  ;; Handle navigation
  )

;; In view function
(item-list/list-view my-list)
;; > Apple
;;   Banana
;;   Cherry

Creation Options

(item-list/item-list items & options)
Option Type Default Description
items vector required Items to display
:height int 0 Visible height (0 = show all)
:width int 0 Width constraint (0 = unlimited)
:cursor int 0 Initial selected index
:title string nil Optional list title
:show-title boolean true Show title if provided
:cursor-prefix string "> " Prefix for selected item
:item-prefix string " " Prefix for unselected items
:show-descriptions boolean false Show item descriptions
:infinite-scroll boolean false Wrap around at ends
:cursor-style style cyan+bold Style for selected item
:item-style style nil Style for unselected items
:title-style style bold Style for title
:id any random Unique identifier

Item Formats

Items can be strings or maps:

;; Simple strings
(item-list/item-list ["Apple" "Banana" "Cherry"])

;; Maps with title and description
(item-list/item-list [{:title "Apple" :description "A red fruit"}
                      {:title "Banana" :description "A yellow fruit"}]
                     :show-descriptions true)

;; Maps with custom keys
(item-list/item-list [{:name "Alice" :role "Admin"}
                      {:name "Bob" :role "User"}])
;; Uses :name as title, :role as description

Key Bindings

Action Keys
Move up Up, k, Ctrl+P
Move down Down, j, Ctrl+N
Page up PgUp, Ctrl+U
Page down PgDn, Ctrl+D
Go to start Home, g
Go to end End, G

Functions

list-update

(item-list/list-update list msg) ; => [list cmd]

Handle navigation messages.

list-view

(item-list/list-view list) ; => "> Apple\n  Banana\n  Cherry"

Render the list as a string.

selected-item

(item-list/selected-item list) ; => "Apple" or {:title "Apple" ...}

Get the currently selected item.

selected-index

(item-list/selected-index list) ; => 0

Get the index of the selected item.

set-items

(item-list/set-items list new-items)

Replace all items, adjusting cursor if needed.

select

(item-list/select list 2)  ; Select item at index 2

Navigation Functions

(item-list/cursor-up list)
(item-list/cursor-down list)
(item-list/page-up list)
(item-list/page-down list)
(item-list/go-to-start list)
(item-list/go-to-end list)

Full Example

(ns my-app
  (:require
   [charm.components.list :as item-list]
   [charm.message :as msg]
   [charm.program :as program]
   [charm.style.core :as style]))

(def items
  [{:title "New File" :description "Create a new file"}
   {:title "Open File" :description "Open an existing file"}
   {:title "Save" :description "Save current file"}
   {:title "Exit" :description "Quit the application"}])

(defn init []
  [{:menu (item-list/item-list items
                               :height 10
                               :show-descriptions true
                               :cursor-style (style/style :fg style/yellow :bold true))}
   nil])

(defn update-fn [state msg]
  (cond
    (msg/key-match? msg "enter")
    (let [selected (item-list/selected-item (:menu state))]
      (println "Selected:" (:title selected))
      (if (= "Exit" (:title selected))
        [state program/quit-cmd]
        [state nil]))

    (msg/key-match? msg "q")
    [state program/quit-cmd]

    :else
    (let [[menu cmd] (item-list/list-update (:menu state) msg)]
      [(assoc state :menu menu) cmd])))

(defn view [state]
  (str "Select an option:\n\n"
       (item-list/list-view (:menu state))
       "\n\nEnter to select, q to quit"))

(program/run {:init init :update update-fn :view view})

Scrolling

When :height is set, the list scrolls to keep the cursor visible:

(item-list/item-list (range 100)
                     :height 10)  ; Shows 10 items, scrolls with cursor

Filtering

;; Filter items by predicate
(item-list/filter-items list #(str/includes? (:title %) "search"))

;; Find and select first match
(item-list/select-first-match list #(= "target" (:title %)))