Liking cljdoc? Tell your friends :D

Program API

The program module provides the main event loop and command system for TUI applications.

Running a Program

run

(charm/run options)

Run a TUI program with the Elm Architecture pattern.

Options:

OptionTypeDefaultDescription
:initfn/valuerequiredInitial state or (fn [] [state cmd])
:updatefnrequired(fn [state msg] [new-state cmd])
:viewfnrequired(fn [state] string)
:alt-screenbooleanfalseUse alternate screen buffer
:mousekeywordnilMouse mode: nil, :normal, :cell, :all
:focus-reportingbooleanfalseReport focus in/out events
:fpsint60Frames per second
:hide-cursorbooleantrueHide terminal cursor

Example:

(charm/run
  {:init {:count 0}
   :update (fn [state msg]
             (cond
               (charm/key-match? msg "q") [state charm/quit-cmd]
               (charm/key-match? msg "up") [(update state :count inc) nil]
               :else [state nil]))
   :view (fn [state]
           (str "Count: " (:count state) "\nPress q to quit"))
   :alt-screen true})

run-simple

(charm/run-simple options)

Simplified version with :state instead of :init.

(charm/run-simple
  {:state {:count 0}
   :update update-fn
   :view view-fn})

Commands

Commands are asynchronous operations that produce messages. They're returned from init and update functions.

cmd

(charm/cmd f)

Create a command from a function that returns a message.

;; Command that sends a message after 1 second
(charm/cmd (fn []
             (Thread/sleep 1000)
             {:type :timer-done}))

batch

(charm/batch & cmds)

Combine multiple commands into one. All commands run in parallel.

(charm/batch
  (charm/cmd #(do-thing-1))
  (charm/cmd #(do-thing-2))
  (charm/cmd #(do-thing-3)))

sequence-cmds

(charm/sequence-cmds & cmds)

Run commands in sequence (each waits for the previous to complete).

(charm/sequence-cmds
  (charm/cmd #(step-1))
  (charm/cmd #(step-2))
  (charm/cmd #(step-3)))

quit-cmd

charm/quit-cmd

A pre-built command that exits the program.

(defn update-fn [state msg]
  (if (charm/key-match? msg "q")
    [state charm/quit-cmd]
    [state nil]))

Init Function

The init option can be:

  1. A value - used as initial state, no startup command
{:init {:count 0}}
  1. A function returning [state cmd]
{:init (fn []
         (let [[timer cmd] (charm/timer-init (charm/timer :timeout 5000))]
           [{:timer timer} cmd]))}
  1. A function returning just state
{:init (fn [] {:count 0})}

Update Function

The update function receives the current state and a message, returning [new-state cmd].

(defn update-fn [state msg]
  (cond
    ;; Handle quit
    (charm/key-match? msg "q")
    [state charm/quit-cmd]

    ;; Handle key press
    (charm/key-match? msg "up")
    [(update state :count inc) nil]

    ;; Handle custom message
    (= :data-loaded (:type msg))
    [(assoc state :data (:data msg)) nil]

    ;; Ignore unhandled messages
    :else
    [state nil]))

View Function

The view function receives state and returns a string to display.

(defn view [state]
  (str "Count: " (:count state) "\n"
       "Press up/down to change, q to quit"))

Mouse Modes

ModeDescription
nilNo mouse support
:normalBasic click events
:cellClick and drag events
:allAll mouse events including motion
(charm/run {:init init
            :update update-fn
            :view view
            :mouse :normal})

Focus Reporting

When enabled, focus events are sent when the terminal gains/loses focus.

(charm/run {:init init
            :update update-fn
            :view view
            :focus-reporting true})

;; In update function
(defn update-fn [state msg]
  (cond
    (charm/focus? msg) [(assoc state :focused true) nil]
    (charm/blur? msg) [(assoc state :focused false) nil]
    :else [state nil]))

Complete Example

(ns my-app
  (:require [charm.core :as charm]))

(defn fetch-data-cmd []
  (charm/cmd (fn []
               ;; Simulate async data fetch
               (Thread/sleep 1000)
               {:type :data-loaded
                :data ["Item 1" "Item 2" "Item 3"]})))

(defn init []
  [{:loading true :data nil}
   (fetch-data-cmd)])

(defn update-fn [state msg]
  (cond
    (charm/key-match? msg "q")
    [state charm/quit-cmd]

    (= :data-loaded (:type msg))
    [(assoc state :loading false :data (:data msg)) nil]

    :else
    [state nil]))

(defn view [state]
  (if (:loading state)
    "Loading..."
    (str "Data:\n" (clojure.string/join "\n" (:data state))
         "\n\nPress q to quit")))

(defn -main [& _args]
  (charm/run {:init init
              :update update-fn
              :view view
              :alt-screen true}))

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close