Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
620 changes: 620 additions & 0 deletions PLAN.md

Large diffs are not rendered by default.

36 changes: 36 additions & 0 deletions doc/api/messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,42 @@ Requires `:focus-reporting true` in run options.
[state nil]))
```

## Environment Messages

### environment

```clojure
(msg/environment color-profile dark-background?)
```

Sent once at startup by `charm/run`, describing the terminal it detected:

| key | value |
|---|---|
| `:color-profile` | `:ascii`, `:ansi`, `:ansi256`, or `:true-color` |
| `:dark-background?` | whether the terminal background is dark |

Colors are already resolved against both for you — see
[Color Profiles](styling.md) and `charm/adaptive`. This message is for apps
that want to branch on the environment themselves, for example to pick an
ASCII fallback for box-drawing characters.

### environment?

```clojure
(msg/environment? msg) ; => boolean
```

```clojure
(defn update-fn [state msg]
(cond
(msg/environment? msg)
[(assoc state :dark? (:dark-background? msg)) nil]

:else
[state nil]))
```

## Quit and Error Messages

### quit
Expand Down
8 changes: 8 additions & 0 deletions doc/api/program.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ Run a TUI program with the Elm Architecture pattern.
| `:focus-reporting` | boolean | `false` | Report focus in/out events |
| `:fps` | int | `60` | Frames per second |
| `:hide-cursor` | boolean | `true` | Hide terminal cursor |
| `:color-profile` | keyword | `nil` | `:ascii`, `:ansi`, `:ansi256` or `:true-color`; `nil` detects from `TERM`/`COLORTERM` |
| `:dark-background?` | boolean | `nil` | `nil` queries the terminal |

The last two pin the [color environment](styling.md#color-profiles) instead of
detecting it, for a terminal that misreports itself or a test that needs a fixed
environment. Pinning `:dark-background?` also skips the OSC 11 background query,
and with it the probe timeout that a terminal which never answers costs at every
startup.

**Example:**

Expand Down
48 changes: 47 additions & 1 deletion doc/api/styling.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,50 @@ Create an ANSI 256 color (0-255).
- 16-231: 6x6x6 color cube
- 232-255: Grayscale ramp

#### adaptive

```clojure
(charm/adaptive light-color dark-color)
```

Create a color that resolves against the terminal's background: `light-color`
is used on light backgrounds, `dark-color` on dark ones.

```clojure
(charm/style :fg (charm/adaptive (charm/hex "#333333")
(charm/hex "#dddddd")))
```

The background is detected once at startup by `charm/run` (OSC 11), and
reported to your app as an [`:environment` message](messages.md). When the
terminal doesn't answer the query, charm assumes a dark background.

### Color Profiles

`charm/run` detects the terminal's color profile at startup and downgrades
colors to fit it, so the same styles work everywhere:

| profile | detected when | colors become |
|---|---|---|
| `:true-color` | `COLORTERM` is `truecolor` or `24bit` | unchanged |
| `:ansi256` | `TERM` contains `256color` | nearest of the 256 palette |
| `:ansi` | any other `TERM` | nearest of the 16 basic colors |

Nearest is JLine's `org.jline.utils.Colors`, which measures distance in CIE Lab
rather than RGB space.
| `:ascii` | `TERM` unset or `dumb` | dropped entirely |

Both halves of the environment can be pinned, for a terminal that misreports
itself or a test that needs a fixed environment:

```clojure
(charm/run {:init ... :update ... :view ...
:color-profile :ansi256
:dark-background? false})
```

Outside of `charm/run` — in tests or scripts — colors are not downgraded.

### Predefined Colors

```clojure
Expand Down Expand Up @@ -195,7 +239,9 @@ charm/bright-white
(charm/style :fg charm/red)
(charm/style :fg (charm/rgb 255 128 0))
(charm/style :fg (charm/hex "#ff8000"))
(charm/style :fg 240) ; ANSI 256 shorthand
(charm/style :fg 240) ; ANSI 256 shorthand
(charm/style :fg :red) ; ANSI 16 name shorthand
(charm/style :fg "#ff8000") ; hex string shorthand

;; Background color
(charm/style :bg charm/blue)
Expand Down
17 changes: 17 additions & 0 deletions src/charm/message.clj
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@
:ctrl ctrl
:shift shift})

(defn environment
"Create an environment message describing the terminal.
Sent once at program startup so apps can branch on the environment.

Keys:
:color-profile - :ascii, :ansi, :ansi256, or :true-color
:dark-background? - whether the terminal background is dark"
[color-profile dark-background?]
{:type :environment
:color-profile color-profile
:dark-background? dark-background?})

(defn focus
"Create a focus gained message."
[]
Expand Down Expand Up @@ -103,6 +115,11 @@
[msg]
(= :mouse (:type msg)))

(defn environment?
"Check if message is an environment message."
[msg]
(= :environment (:type msg)))

(defn focus?
"Check if message is a focus event."
[msg]
Expand Down
Loading
Loading