Compare commits

..

70 Commits

Author SHA1 Message Date
Josh McKinney
e7831aedd4 chore: release 0.30.0-alpha.1 (#1618)
Versions:

```
ratatui = { path = "ratatui", version = "0.30.0-alpha.1" }
ratatui-core = { path = "ratatui-core", version = "0.1.0-alpha.2" }
ratatui-crossterm = { path = "ratatui-crossterm", version = "0.1.0-alpha.1" }
ratatui-termion = { path = "ratatui-termion", version = "0.1.0-alpha.1" }
ratatui-termwiz = { path = "ratatui-termwiz", version = "0.1.0-alpha.1" }
ratatui-widgets = { path = "ratatui-widgets", version = "0.3.0-alpha.1" }
```
2025-01-15 15:31:38 -08:00
Josh McKinney
4a871f993e ci: refactor xtask / toml formatting (#1602)
- format toml files using taplo
- add toml formatting check to CI
- use xtask consistently from bacon
- refactor xtask commands to take params instead of multiple commands
2025-01-14 14:20:05 -08:00
Josh McKinney
da05957fa0 docs: add widget-ref-container example (#1603)
Implements ideas alluded to by
<https://discord.com/channels/1070692720437383208/1072907135664529508/1323061053990637640>
and followup conversations.
2025-01-14 14:05:58 -08:00
dependabot[bot]
41d883da7a chore(deps): bump serde_json from 1.0.134 to 1.0.135 (#1614)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.134 to
1.0.135.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/serde-rs/json/releases">serde_json's
releases</a>.</em></p>
<blockquote>
<h2>v1.0.135</h2>
<ul>
<li>Add serde_json::Map::into_values method (<a
href="https://redirect.github.com/serde-rs/json/issues/1226">#1226</a>,
thanks <a
href="https://github.com/tisonkun"><code>@​tisonkun</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="9802c08d4e"><code>9802c08</code></a>
Release 1.0.135</li>
<li><a
href="b97935fde2"><code>b97935f</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/json/issues/1226">#1226</a>
from tisonkun/map-into-values</li>
<li><a
href="d48c224d12"><code>d48c224</code></a>
Add Map::into_values method</li>
<li><a
href="1e77cac742"><code>1e77cac</code></a>
Resolve precedence clippy lint</li>
<li>See full diff in <a
href="https://github.com/serde-rs/json/compare/v1.0.134...v1.0.135">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde_json&package-manager=cargo&previous-version=1.0.134&new-version=1.0.135)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-14 20:31:20 +03:00
dependabot[bot]
0552223511 chore(deps): bump rstest from 0.23.0 to 0.24.0 (#1610)
Bumps [rstest](https://github.com/la10736/rstest) from 0.23.0 to 0.24.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/la10736/rstest/releases">rstest's
releases</a>.</em></p>
<blockquote>
<h2>0.24.0</h2>
<h2>What's Changed</h2>
<ul>
<li>refactor: use <code>core</code> instead of <code>std</code> by <a
href="https://github.com/rnbguy"><code>@​rnbguy</code></a> in <a
href="https://redirect.github.com/la10736/rstest/pull/283">la10736/rstest#283</a></li>
<li>Fix msrv and complete no_std support by <a
href="https://github.com/la10736"><code>@​la10736</code></a> in <a
href="https://redirect.github.com/la10736/rstest/pull/285">la10736/rstest#285</a></li>
<li>replace futures with futures-util by <a
href="https://github.com/mati865"><code>@​mati865</code></a> in <a
href="https://redirect.github.com/la10736/rstest/pull/288">la10736/rstest#288</a></li>
<li>Introduce Context by <a
href="https://github.com/la10736"><code>@​la10736</code></a> in <a
href="https://redirect.github.com/la10736/rstest/pull/289">la10736/rstest#289</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/rnbguy"><code>@​rnbguy</code></a> made
their first contribution in <a
href="https://redirect.github.com/la10736/rstest/pull/283">la10736/rstest#283</a></li>
<li><a href="https://github.com/mati865"><code>@​mati865</code></a> made
their first contribution in <a
href="https://redirect.github.com/la10736/rstest/pull/288">la10736/rstest#288</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/la10736/rstest/compare/v0.23.0...v0.24.0">https://github.com/la10736/rstest/compare/v0.23.0...v0.24.0</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/la10736/rstest/blob/master/CHANGELOG.md">rstest's
changelog</a>.</em></p>
<blockquote>
<h2>[0.24.0] 2025/1/1</h2>
<h3>Changed</h3>
<ul>
<li>MSRV to 1.70.0 (see <a
href="https://redirect.github.com/la10736/rstest/issues/284">#284</a>
thanks to <a
href="https://github.com/rnbguy"><code>@​rnbguy</code></a>)</li>
</ul>
<h3>Add</h3>
<ul>
<li><code>#![no_std]</code> support: now you can use <code>rstest</code>
also in <code>no_std</code> lib
(see <a
href="https://redirect.github.com/la10736/rstest/issues/282">#282</a>
thanks to <a
href="https://github.com/rnbguy"><code>@​rnbguy</code></a>)</li>
<li><code>#[context]</code> to have test function name and other useful
thighs on
the tip of your fingers (see <a
href="https://redirect.github.com/la10736/rstest/issues/177">#177</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="d57af90f16"><code>d57af90</code></a>
Prepare release</li>
<li><a
href="dfc4ff0e42"><code>dfc4ff0</code></a>
Make clippy happy</li>
<li><a
href="01140c13a1"><code>01140c1</code></a>
Docs and changelog</li>
<li><a
href="4a9763f2fe"><code>4a9763f</code></a>
1. Test also matrix case</li>
<li><a
href="d77d7c6a48"><code>d77d7c6</code></a>
Base implementation</li>
<li><a
href="7792a9b7bc"><code>7792a9b</code></a>
Add the ability to run CI test on demand</li>
<li><a
href="11869b587c"><code>11869b5</code></a>
Don't add channel if the env is not provided explicitly.</li>
<li><a
href="9a78bfb78f"><code>9a78bfb</code></a>
replace futures with futures-util</li>
<li><a
href="88f9c2ef6f"><code>88f9c2e</code></a>
<a href="https://redirect.github.com/la10736/rstest/issues/282">#282</a>
: add e2e test, cover also the once fixture case and add cheange log
lines</li>
<li><a
href="cb5db35f26"><code>cb5db35</code></a>
Close <a
href="https://redirect.github.com/la10736/rstest/issues/284">#284</a>
and add a test to check msrv on rendered code.</li>
<li>Additional commits viewable in <a
href="https://github.com/la10736/rstest/compare/v0.23.0...v0.24.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rstest&package-manager=cargo&previous-version=0.23.0&new-version=0.24.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-14 20:31:03 +03:00
dependabot[bot]
21a561b1b3 chore(deps): bump tokio from 1.42.0 to 1.43.0 (#1613)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.42.0 to 1.43.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/tokio-rs/tokio/releases">tokio's
releases</a>.</em></p>
<blockquote>
<h2>Tokio v1.43.0</h2>
<h1>1.43.0 (Jan 8th, 2025)</h1>
<h3>Added</h3>
<ul>
<li>net: add <code>UdpSocket::peek</code> methods (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7068">#7068</a>)</li>
<li>net: add support for Haiku OS (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7042">#7042</a>)</li>
<li>process: add <code>Command::into_std()</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7014">#7014</a>)</li>
<li>signal: add <code>SignalKind::info</code> on illumos (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6995">#6995</a>)</li>
<li>signal: add support for realtime signals on illumos (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7029">#7029</a>)</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>io: don't call <code>set_len</code> before initializing vector in
<code>Blocking</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7054">#7054</a>)</li>
<li>macros: suppress <code>clippy::needless_return</code> in
<code>#[tokio::main]</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6874">#6874</a>)</li>
<li>runtime: fix thread parking on WebAssembly (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7041">#7041</a>)</li>
</ul>
<h3>Changes</h3>
<ul>
<li>chore: use unsync loads for <code>unsync_load</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7073">#7073</a>)</li>
<li>io: use <code>Buf::put_bytes</code> in <code>Repeat</code> read impl
(<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7055">#7055</a>)</li>
<li>task: drop the join waker of a task eagerly (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6986">#6986</a>)</li>
</ul>
<h3>Changes to unstable APIs</h3>
<ul>
<li>metrics: improve flexibility of H2Histogram Configuration (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6963">#6963</a>)</li>
<li>taskdump: add accessor methods for backtrace (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6975">#6975</a>)</li>
</ul>
<h3>Documented</h3>
<ul>
<li>io: clarify <code>ReadBuf::uninit</code> allows initialized buffers
as well (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7053">#7053</a>)</li>
<li>net: fix ambiguity in <code>TcpStream::try_write_vectored</code>
docs (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7067">#7067</a>)</li>
<li>runtime: fix <code>LocalRuntime</code> doc links (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7074">#7074</a>)</li>
<li>sync: extend documentation for
<code>watch::Receiver::wait_for</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7038">#7038</a>)</li>
<li>sync: fix typos in <code>OnceCell</code> docs (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7047">#7047</a>)</li>
</ul>
<p><a
href="https://redirect.github.com/tokio-rs/tokio/issues/6874">#6874</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/6874">tokio-rs/tokio#6874</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6963">#6963</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/6963">tokio-rs/tokio#6963</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6975">#6975</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/6975">tokio-rs/tokio#6975</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6986">#6986</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/6986">tokio-rs/tokio#6986</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6995">#6995</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/6995">tokio-rs/tokio#6995</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7014">#7014</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/7014">tokio-rs/tokio#7014</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7029">#7029</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/7029">tokio-rs/tokio#7029</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7038">#7038</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/7038">tokio-rs/tokio#7038</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7041">#7041</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/7041">tokio-rs/tokio#7041</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7042">#7042</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/7042">tokio-rs/tokio#7042</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7047">#7047</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/7047">tokio-rs/tokio#7047</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7053">#7053</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/7053">tokio-rs/tokio#7053</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7054">#7054</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/7054">tokio-rs/tokio#7054</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7055">#7055</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/7055">tokio-rs/tokio#7055</a></p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="5f3296df77"><code>5f3296d</code></a>
chore: prepare Tokio v1.43.0 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7079">#7079</a>)</li>
<li><a
href="cc974a646b"><code>cc974a6</code></a>
chore: prepare tokio-macros v2.5.0 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7078">#7078</a>)</li>
<li><a
href="15495fd883"><code>15495fd</code></a>
metrics: improve flexibility of H2Histogram Configuration (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6963">#6963</a>)</li>
<li><a
href="ad4183412a"><code>ad41834</code></a>
io: don't call <code>set_len</code> before initializing vector in
<code>Blocking</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7054">#7054</a>)</li>
<li><a
href="bd3e857737"><code>bd3e857</code></a>
runtime: move <code>is_join_waker_set</code> assertion in
<code>unset_waker</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7072">#7072</a>)</li>
<li><a
href="15f73666f1"><code>15f7366</code></a>
runtime: fix <code>LocalRuntime</code> doc links (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7074">#7074</a>)</li>
<li><a
href="fd2048dad1"><code>fd2048d</code></a>
ci: split miri jobs into unit and integration tests (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7071">#7071</a>)</li>
<li><a
href="e8f39157b6"><code>e8f3915</code></a>
chore: use unsync loads for <code>unsync_load</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7073">#7073</a>)</li>
<li><a
href="67f127769b"><code>67f1277</code></a>
net: fix ambiguity in <code>TcpStream::try_write_vectored</code> docs
(<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7067">#7067</a>)</li>
<li><a
href="463502cbaf"><code>463502c</code></a>
io: clarify <code>ReadBuf::uninit</code> allows initialized buffers as
well (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7053">#7053</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/tokio-rs/tokio/compare/tokio-1.42.0...tokio-1.43.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tokio&package-manager=cargo&previous-version=1.42.0&new-version=1.43.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 13:18:16 -08:00
dependabot[bot]
079d74ce14 chore(deps): bump bitflags from 2.6.0 to 2.7.0 (#1615)
Bumps [bitflags](https://github.com/bitflags/bitflags) from 2.6.0 to
2.7.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/bitflags/bitflags/releases">bitflags's
releases</a>.</em></p>
<blockquote>
<h2>2.7.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix <code>clippy::doc_lazy_continuation</code> lints by <a
href="https://github.com/waywardmonkeys"><code>@​waywardmonkeys</code></a>
in <a
href="https://redirect.github.com/bitflags/bitflags/pull/414">bitflags/bitflags#414</a></li>
<li>Run clippy on extra features in CI. by <a
href="https://github.com/waywardmonkeys"><code>@​waywardmonkeys</code></a>
in <a
href="https://redirect.github.com/bitflags/bitflags/pull/415">bitflags/bitflags#415</a></li>
<li>Fix CI: trybuild refresh, allow some clippy restrictions. by <a
href="https://github.com/waywardmonkeys"><code>@​waywardmonkeys</code></a>
in <a
href="https://redirect.github.com/bitflags/bitflags/pull/417">bitflags/bitflags#417</a></li>
<li>Update zerocopy version in example by <a
href="https://github.com/KodrAus"><code>@​KodrAus</code></a> in <a
href="https://redirect.github.com/bitflags/bitflags/pull/422">bitflags/bitflags#422</a></li>
<li>Add method to check if unknown bits are set by <a
href="https://github.com/wysiwys"><code>@​wysiwys</code></a> in <a
href="https://redirect.github.com/bitflags/bitflags/pull/426">bitflags/bitflags#426</a></li>
<li>Update error messages by <a
href="https://github.com/KodrAus"><code>@​KodrAus</code></a> in <a
href="https://redirect.github.com/bitflags/bitflags/pull/427">bitflags/bitflags#427</a></li>
<li>Add <code>truncate(&amp;mut self)</code> method to unset unknown
bits by <a href="https://github.com/wysiwys"><code>@​wysiwys</code></a>
in <a
href="https://redirect.github.com/bitflags/bitflags/pull/428">bitflags/bitflags#428</a></li>
<li>Update error messages by <a
href="https://github.com/KodrAus"><code>@​KodrAus</code></a> in <a
href="https://redirect.github.com/bitflags/bitflags/pull/429">bitflags/bitflags#429</a></li>
<li>Prepare for 2.7.0 release by <a
href="https://github.com/KodrAus"><code>@​KodrAus</code></a> in <a
href="https://redirect.github.com/bitflags/bitflags/pull/430">bitflags/bitflags#430</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/wysiwys"><code>@​wysiwys</code></a> made
their first contribution in <a
href="https://redirect.github.com/bitflags/bitflags/pull/426">bitflags/bitflags#426</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/bitflags/bitflags/compare/2.6.0...2.7.0">https://github.com/bitflags/bitflags/compare/2.6.0...2.7.0</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/bitflags/bitflags/blob/main/CHANGELOG.md">bitflags's
changelog</a>.</em></p>
<blockquote>
<h1>2.7.0</h1>
<h2>What's Changed</h2>
<ul>
<li>Fix <code>clippy::doc_lazy_continuation</code> lints by <a
href="https://github.com/waywardmonkeys"><code>@​waywardmonkeys</code></a>
in <a
href="https://redirect.github.com/bitflags/bitflags/pull/414">bitflags/bitflags#414</a></li>
<li>Run clippy on extra features in CI. by <a
href="https://github.com/waywardmonkeys"><code>@​waywardmonkeys</code></a>
in <a
href="https://redirect.github.com/bitflags/bitflags/pull/415">bitflags/bitflags#415</a></li>
<li>Fix CI: trybuild refresh, allow some clippy restrictions. by <a
href="https://github.com/waywardmonkeys"><code>@​waywardmonkeys</code></a>
in <a
href="https://redirect.github.com/bitflags/bitflags/pull/417">bitflags/bitflags#417</a></li>
<li>Update zerocopy version in example by <a
href="https://github.com/KodrAus"><code>@​KodrAus</code></a> in <a
href="https://redirect.github.com/bitflags/bitflags/pull/422">bitflags/bitflags#422</a></li>
<li>Add method to check if unknown bits are set by <a
href="https://github.com/wysiwys"><code>@​wysiwys</code></a> in <a
href="https://redirect.github.com/bitflags/bitflags/pull/426">bitflags/bitflags#426</a></li>
<li>Update error messages by <a
href="https://github.com/KodrAus"><code>@​KodrAus</code></a> in <a
href="https://redirect.github.com/bitflags/bitflags/pull/427">bitflags/bitflags#427</a></li>
<li>Add <code>truncate(&amp;mut self)</code> method to unset unknown
bits by <a href="https://github.com/wysiwys"><code>@​wysiwys</code></a>
in <a
href="https://redirect.github.com/bitflags/bitflags/pull/428">bitflags/bitflags#428</a></li>
<li>Update error messages by <a
href="https://github.com/KodrAus"><code>@​KodrAus</code></a> in <a
href="https://redirect.github.com/bitflags/bitflags/pull/429">bitflags/bitflags#429</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/wysiwys"><code>@​wysiwys</code></a> made
their first contribution in <a
href="https://redirect.github.com/bitflags/bitflags/pull/426">bitflags/bitflags#426</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/bitflags/bitflags/compare/2.6.0...2.7.0">https://github.com/bitflags/bitflags/compare/2.6.0...2.7.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="10b9fd3a9e"><code>10b9fd3</code></a>
Merge pull request <a
href="https://redirect.github.com/bitflags/bitflags/issues/430">#430</a>
from bitflags/cargo/2.7.0</li>
<li><a
href="137485a2c2"><code>137485a</code></a>
prepare for 2.7.0 release</li>
<li><a
href="6c0dfa4a0c"><code>6c0dfa4</code></a>
Merge pull request <a
href="https://redirect.github.com/bitflags/bitflags/issues/429">#429</a>
from bitflags/fix/err-msgs-2</li>
<li><a
href="451fdf4778"><code>451fdf4</code></a>
update rust before building</li>
<li><a
href="f5ac5b14e5"><code>f5ac5b1</code></a>
update error messages</li>
<li><a
href="30901e6dee"><code>30901e6</code></a>
Merge pull request <a
href="https://redirect.github.com/bitflags/bitflags/issues/428">#428</a>
from wysiwys/main</li>
<li><a
href="7b9ecab84d"><code>7b9ecab</code></a>
add <code>truncate(&amp;mut self)</code> method to unset unknown
bits</li>
<li><a
href="85983a4b1c"><code>85983a4</code></a>
Merge pull request <a
href="https://redirect.github.com/bitflags/bitflags/issues/427">#427</a>
from bitflags/ci/error-msgs</li>
<li><a
href="f00779337d"><code>f007793</code></a>
remove match case</li>
<li><a
href="6ebcd190a2"><code>6ebcd19</code></a>
add test case for match statement</li>
<li>Additional commits viewable in <a
href="https://github.com/bitflags/bitflags/compare/2.6.0...2.7.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=bitflags&package-manager=cargo&previous-version=2.6.0&new-version=2.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 13:17:41 -08:00
dependabot[bot]
22ec4f7414 chore(deps): bump instability from 0.3.6 to 0.3.7 (#1616)
Bumps [instability](https://github.com/ratatui-org/instability) from
0.3.6 to 0.3.7.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/ratatui-org/instability/releases">instability's
releases</a>.</em></p>
<blockquote>
<h2>instability-example-v0.3.7</h2>
<h3>Other</h3>
<ul>
<li>Add #[allow(unused_imports)] lint to unstable reexports (<a
href="https://redirect.github.com/ratatui/instability/pull/21">#21</a>)</li>
</ul>
<h2>instability-v0.3.7</h2>
<h3>Other</h3>
<ul>
<li>Add #[allow(unused_imports)] lint to unstable reexports (<a
href="https://redirect.github.com/ratatui/instability/pull/21">#21</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ratatui/instability/blob/main/CHANGELOG.md">instability's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/ratatui/instability/compare/instability-v0.3.6...instability-v0.3.7">0.3.7</a>
- 2025-01-10</h2>
<h3>Other</h3>
<ul>
<li>Add #[allow(unused_imports)] lint to unstable reexports (<a
href="https://redirect.github.com/ratatui/instability/pull/21">#21</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="c9ae88731b"><code>c9ae887</code></a>
chore: release v0.3.7 (<a
href="https://redirect.github.com/ratatui-org/instability/issues/22">#22</a>)</li>
<li><a
href="cf3e49aa16"><code>cf3e49a</code></a>
Add #[allow(unused_imports)] lint to unstable reexports (<a
href="https://redirect.github.com/ratatui-org/instability/issues/21">#21</a>)</li>
<li>See full diff in <a
href="https://github.com/ratatui-org/instability/compare/instability-v0.3.6...instability-v0.3.7">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=instability&package-manager=cargo&previous-version=0.3.6&new-version=0.3.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 13:16:24 -08:00
Josh McKinney
6f213191ef chore: rename examples with clashing names (#1597)
These will eventually be moved / consolidated elsewhere, but this clears
the warnings while building for now.
2025-01-11 00:10:54 +03:00
Josh McKinney
088aac136d docs(readme): tweak links and badges (#1598) 2025-01-11 00:06:52 +03:00
Josh McKinney
a692a6e371 fix(lint): apply rust 1.84 clippy suggestions (#1612)
The canvas map constants are now statics instead.
Fixes
https://rust-lang.github.io/rust-clippy/master/index.html\#large_const_arrays
2025-01-10 23:17:07 +03:00
dawe
1798512e94 docs: fix wording in user_input example (#1611)
Fix wording in `user_input.rs` example.
2025-01-07 19:25:47 +03:00
dependabot[bot]
32f3833a6d chore(deps): bump clap-cargo from 0.14.1 to 0.15.1 (#1608)
Bumps [clap-cargo](https://github.com/crate-ci/clap-cargo) from 0.14.1
to 0.15.1.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/crate-ci/clap-cargo/blob/master/CHANGELOG.md">clap-cargo's
changelog</a>.</em></p>
<blockquote>
<h2>[0.15.1] - 2025-01-03</h2>
<h3>Fix</h3>
<ul>
<li>Reduce <code>Cargo.lock</code> content</li>
</ul>
<h2>[0.15.0] - 2025-01-02</h2>
<h3>Breaking Changes</h3>
<ul>
<li>Upgraded <code>cargo_metadata</code> to 0.19</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="3eadd0f476"><code>3eadd0f</code></a>
chore: Release clap-cargo version 0.15.1</li>
<li><a
href="427af69642"><code>427af69</code></a>
docs: Update changelog</li>
<li><a
href="a37548f05b"><code>a37548f</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/clap-cargo/issues/79">#79</a>
from dtolnay-contrib/deps</li>
<li><a
href="80914f3015"><code>80914f3</code></a>
chore: Omit serde/serde_json from lockfiles not using
cargo_metadata</li>
<li><a
href="9b76d52f24"><code>9b76d52</code></a>
chore: Release clap-cargo version 0.15.0</li>
<li><a
href="bb2590c3af"><code>bb2590c</code></a>
docs: Update changelog</li>
<li><a
href="b44569a3ce"><code>b44569a</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/clap-cargo/issues/78">#78</a>
from epage/renovate/cargo_metadata-0.x</li>
<li><a
href="28a8c00d3f"><code>28a8c00</code></a>
chore(deps)!: Update Rust crate cargo_metadata to 0.19</li>
<li><a
href="4f485ee5de"><code>4f485ee</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/clap-cargo/issues/77">#77</a>
from crate-ci/renovate/stable-1.x</li>
<li><a
href="cfe5cacab3"><code>cfe5cac</code></a>
chore(deps): Update dependency STABLE to v1.83.0</li>
<li>Additional commits viewable in <a
href="https://github.com/crate-ci/clap-cargo/compare/v0.14.1...v0.15.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=clap-cargo&package-manager=cargo&previous-version=0.14.1&new-version=0.15.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-06 18:25:23 +03:00
dependabot[bot]
2ccc40e116 chore(deps): bump instability from 0.3.5 to 0.3.6 (#1609)
Bumps [instability](https://github.com/ratatui-org/instability) from
0.3.5 to 0.3.6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/ratatui-org/instability/releases">instability's
releases</a>.</em></p>
<blockquote>
<h2>instability-example-v0.3.6</h2>
<h3>Added</h3>
<ul>
<li>Allow marking impl blocks unstable/stable (<a
href="https://redirect.github.com/ratatui-org/instability/issues/15">#15</a>)</li>
<li>add stable macro (<a
href="https://redirect.github.com/ratatui-org/instability/issues/14">#14</a>)</li>
<li>use doc(cfg)</li>
<li>allow use statements to be marked unstable (<a
href="https://redirect.github.com/ratatui-org/instability/issues/3">#3</a>)</li>
</ul>
<h3>Other</h3>
<ul>
<li>prepare instability-example for publish (<a
href="https://redirect.github.com/ratatui-org/instability/issues/18">#18</a>)</li>
<li>bump msrv to 1.63</li>
<li>tweak doc wording and formatting (<a
href="https://redirect.github.com/ratatui-org/instability/issues/4">#4</a>)</li>
<li>fork and change name to instabilty</li>
<li>Apply visibility restriction to struct fields (<a
href="https://redirect.github.com/ratatui/instability/pull/10">#10</a>)</li>
<li>Update to Rust edition 2021 (<a
href="https://redirect.github.com/ratatui/instability/pull/9">#9</a>)</li>
<li>Add issue tracking</li>
<li>Initial version</li>
</ul>
<h2>instability-v0.3.6</h2>
<h3>Other</h3>
<ul>
<li>Move pretty_assertions to dev-dependencies (<a
href="https://redirect.github.com/ratatui/instability/pull/19">#19</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ratatui/instability/blob/main/CHANGELOG.md">instability's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/ratatui/instability/compare/instability-v0.3.5...instability-v0.3.6">0.3.6</a>
- 2025-01-04</h2>
<h3>Other</h3>
<ul>
<li>Move pretty_assertions to dev-dependencies (<a
href="https://redirect.github.com/ratatui/instability/pull/19">#19</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="cf84fbe505"><code>cf84fbe</code></a>
chore: release v0.3.6 (<a
href="https://redirect.github.com/ratatui-org/instability/issues/20">#20</a>)</li>
<li><a
href="5eca2ee0d1"><code>5eca2ee</code></a>
Move pretty_assertions to dev-dependencies (<a
href="https://redirect.github.com/ratatui-org/instability/issues/19">#19</a>)</li>
<li>See full diff in <a
href="https://github.com/ratatui-org/instability/compare/instability-v0.3.5...instability-v0.3.6">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=instability&package-manager=cargo&previous-version=0.3.5&new-version=0.3.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-06 18:24:20 +03:00
dependabot[bot]
019e34e006 chore(deps): bump serde from 1.0.216 to 1.0.217 (#1600)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.216 to
1.0.217.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/serde-rs/serde/releases">serde's
releases</a>.</em></p>
<blockquote>
<h2>v1.0.217</h2>
<ul>
<li>Support serializing externally tagged unit variant inside flattened
field (<a
href="https://redirect.github.com/serde-rs/serde/issues/2786">#2786</a>,
thanks <a
href="https://github.com/Mingun"><code>@​Mingun</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="930401b0dd"><code>930401b</code></a>
Release 1.0.217</li>
<li><a
href="cb6eaea151"><code>cb6eaea</code></a>
Fix roundtrip inconsistency:</li>
<li><a
href="b6f339ca36"><code>b6f339c</code></a>
Resolve repr_packed_without_abi clippy lint in tests</li>
<li><a
href="2a5caea1a8"><code>2a5caea</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/serde/issues/2872">#2872</a>
from dtolnay/ehpersonality</li>
<li><a
href="b9f93f99aa"><code>b9f93f9</code></a>
Add no-std CI on stable compiler</li>
<li><a
href="eb5cd476ba"><code>eb5cd47</code></a>
Drop #[lang = &quot;eh_personality&quot;] from no-std test</li>
<li><a
href="8478a3b7dd"><code>8478a3b</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/serde/issues/2871">#2871</a>
from dtolnay/nostdstart</li>
<li><a
href="dbb909136e"><code>dbb9091</code></a>
Replace #[start] with extern fn main</li>
<li>See full diff in <a
href="https://github.com/serde-rs/serde/compare/v1.0.216...v1.0.217">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde&package-manager=cargo&previous-version=1.0.216&new-version=1.0.217)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-30 22:24:53 +03:00
Josh McKinney
11cbb2ba87 chore: use cargo xtask for bacon clippy command (#1592) 2024-12-29 11:49:41 -08:00
n4n5
50ba96518f feat: add a new RatatuiMascot widget (#1584)
Move the Mascot from Demo2 into a new widget.
Make the Rat grey and adjust the other colors.

```rust
frame.render_widget(RatatuiMascot::default(), frame.area());
```
2024-12-26 04:32:38 -08:00
Josh McKinney
904b0aa723 refactor: move symbols to modules (#1594) 2024-12-26 04:05:05 -08:00
Josh McKinney
b544e394c9 chore: use clap instead of argh for demo example (#1591) 2024-12-24 22:45:39 -08:00
Josh McKinney
1d28c89fe5 feat: add conversions for anstyle (#1581)
https://crates.io/crates/anstyle makes it possible to define colors in
an interoperable way. This makes it possible for applications to easily
load colors from a variety of formats.

This is gated by the anstyle feature flag which is disabled by default.

---------

Co-authored-by: Orhun Parmaksız <orhun@archlinux.org>
2024-12-24 12:03:14 -08:00
dependabot[bot]
1d2882636e chore(deps): bump serde_json from 1.0.133 to 1.0.134 (#1586)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.133 to
1.0.134.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/serde-rs/json/releases">serde_json's
releases</a>.</em></p>
<blockquote>
<h2>v1.0.134</h2>
<ul>
<li>Add <code>RawValue</code> associated constants for literal
<code>null</code>, <code>true</code>, <code>false</code> (<a
href="https://redirect.github.com/serde-rs/json/issues/1221">#1221</a>,
thanks <a
href="https://github.com/bheylin"><code>@​bheylin</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="b2a1415aad"><code>b2a1415</code></a>
Release 1.0.134</li>
<li><a
href="9875785f24"><code>9875785</code></a>
Tweak wording of NULL/TRUE/FALSE documentation</li>
<li><a
href="4aa05b9143"><code>4aa05b9</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/json/issues/1222">#1222</a>
from dtolnay/rawvalueassoc</li>
<li><a
href="f42c7c760b"><code>f42c7c7</code></a>
Move RawValue associated constants into same impl block as public
functions</li>
<li><a
href="96576bad53"><code>96576ba</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/json/issues/1221">#1221</a>
from bheylin/add-const-raw-values-for-null-and-bools</li>
<li><a
href="4db66fb0b2"><code>4db66fb</code></a>
Add <code>'static</code> lifetime to <code>const</code>'s</li>
<li><a
href="9c9aa1f380"><code>9c9aa1f</code></a>
Add literal 'null', 'true' and 'false' consts to <code>RawValue</code>
struct.</li>
<li>See full diff in <a
href="https://github.com/serde-rs/json/compare/v1.0.133...v1.0.134">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde_json&package-manager=cargo&previous-version=1.0.133&new-version=1.0.134)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-24 11:39:39 -08:00
dependabot[bot]
157cb3401b chore(deps): bump clap-verbosity-flag from 3.0.1 to 3.0.2 (#1587)
Bumps
[clap-verbosity-flag](https://github.com/clap-rs/clap-verbosity-flag)
from 3.0.1 to 3.0.2.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/clap-rs/clap-verbosity-flag/blob/master/CHANGELOG.md">clap-verbosity-flag's
changelog</a>.</em></p>
<blockquote>
<h2>[3.0.2] - 2024-12-16</h2>
<h3>Features</h3>
<ul>
<li>Add a <code>Copy</code> impl to <code>Verbosity</code></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="8a65b98d9b"><code>8a65b98</code></a>
chore: Release clap-verbosity-flag version 3.0.2</li>
<li><a
href="6f634c99b2"><code>6f634c9</code></a>
docs: Update changelog</li>
<li><a
href="bcfc9e88f6"><code>bcfc9e8</code></a>
Merge pull request <a
href="https://redirect.github.com/clap-rs/clap-verbosity-flag/issues/133">#133</a>
from joshka/jm/verbosity-copy</li>
<li><a
href="9191996bed"><code>9191996</code></a>
feat: Impl Copy for Verbosity</li>
<li><a
href="9f72d6c034"><code>9f72d6c</code></a>
Merge pull request <a
href="https://redirect.github.com/clap-rs/clap-verbosity-flag/issues/131">#131</a>
from clap-rs/renovate/stable-1.x</li>
<li><a
href="3c00cdad77"><code>3c00cda</code></a>
chore(deps): Update compatible (dev) (<a
href="https://redirect.github.com/clap-rs/clap-verbosity-flag/issues/130">#130</a>)</li>
<li><a
href="061da5a9ef"><code>061da5a</code></a>
chore(deps): Update dependency STABLE to v1.83.0</li>
<li>See full diff in <a
href="https://github.com/clap-rs/clap-verbosity-flag/compare/v3.0.1...v3.0.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=clap-verbosity-flag&package-manager=cargo&previous-version=3.0.1&new-version=3.0.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-24 11:39:07 -08:00
dependabot[bot]
3d0c96a838 chore(deps): bump instability from 0.3.3 to 0.3.5 (#1588)
Bumps [instability](https://github.com/ratatui-org/instability) from
0.3.3 to 0.3.5.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/ratatui-org/instability/releases">instability's
releases</a>.</em></p>
<blockquote>
<h2>instability-example-v0.3.5</h2>
<h3>Added</h3>
<ul>
<li>Allow marking impl blocks unstable/stable (<a
href="https://redirect.github.com/ratatui-org/instability/issues/15">#15</a>)</li>
<li>add stable macro (<a
href="https://redirect.github.com/ratatui-org/instability/issues/14">#14</a>)</li>
<li>use doc(cfg)</li>
<li>allow use statements to be marked unstable (<a
href="https://redirect.github.com/ratatui-org/instability/issues/3">#3</a>)</li>
</ul>
<h3>Other</h3>
<ul>
<li>prepare instability-example for publish (<a
href="https://redirect.github.com/ratatui-org/instability/issues/18">#18</a>)</li>
<li>bump msrv to 1.63</li>
<li>tweak doc wording and formatting (<a
href="https://redirect.github.com/ratatui-org/instability/issues/4">#4</a>)</li>
<li>fork and change name to instabilty</li>
<li>Apply visibility restriction to struct fields (<a
href="https://redirect.github.com/ratatui/instability/pull/10">#10</a>)</li>
<li>Update to Rust edition 2021 (<a
href="https://redirect.github.com/ratatui/instability/pull/9">#9</a>)</li>
<li>Add issue tracking</li>
<li>Initial version</li>
</ul>
<h2>instability-v0.3.5</h2>
<h3>Other</h3>
<ul>
<li>prepare instability-example for publish (<a
href="https://redirect.github.com/ratatui-org/instability/issues/18">#18</a>)</li>
<li>clippy --fix</li>
</ul>
<h2>instability-example-v0.3.4</h2>
<p>No release notes provided.</p>
<h2>instability-v0.3.4</h2>
<h3>Added</h3>
<ul>
<li>Allow marking impl blocks unstable/stable (<a
href="https://redirect.github.com/ratatui/instability/pull/15">#15</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ratatui/instability/blob/main/CHANGELOG.md">instability's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/ratatui/instability/compare/instability-v0.3.4...instability-v0.3.5">0.3.5</a>
- 2024-12-21</h2>
<h3>Other</h3>
<ul>
<li>prepare instability-example for publish (<a
href="https://redirect.github.com/ratatui-org/instability/issues/18">#18</a>)</li>
<li>clippy --fix</li>
</ul>
<h2><a
href="https://github.com/ratatui/instability/compare/instability-v0.3.3...instability-v0.3.4">0.3.4</a>
- 2024-12-21</h2>
<h3>Added</h3>
<ul>
<li>Allow marking impl blocks unstable/stable (<a
href="https://redirect.github.com/ratatui/instability/pull/15">#15</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="6420472e5b"><code>6420472</code></a>
chore: release v0.3.5 (<a
href="https://redirect.github.com/ratatui-org/instability/issues/17">#17</a>)</li>
<li><a
href="308c590e9e"><code>308c590</code></a>
docs: prepare instability-example for publish (<a
href="https://redirect.github.com/ratatui-org/instability/issues/18">#18</a>)</li>
<li><a
href="7655288648"><code>7655288</code></a>
chore: clippy --fix</li>
<li><a
href="0762e064c2"><code>0762e06</code></a>
chore: release v0.3.4 (<a
href="https://redirect.github.com/ratatui-org/instability/issues/16">#16</a>)</li>
<li><a
href="596e13c00d"><code>596e13c</code></a>
feat: Allow marking impl blocks unstable/stable (<a
href="https://redirect.github.com/ratatui-org/instability/issues/15">#15</a>)</li>
<li>See full diff in <a
href="https://github.com/ratatui-org/instability/compare/instability-v0.3.3...instability-v0.3.5">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=instability&package-manager=cargo&previous-version=0.3.3&new-version=0.3.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-24 11:37:27 -08:00
dawe
03066d81bf docs: fix punctuation in canvas.rs documentation (#1583)
Fix end of sentence punctuation in canvas.rs docs.
2024-12-21 03:49:44 -05:00
Orhun Parmaksız
5f57d35234 chore(examples): add colors explorer demo app (#1580)
related #1512 

Moves the colors examples to apps

Co-authored-by: Josh McKinney <joshka@users.noreply.github.com>
2024-12-18 20:09:17 -08:00
Orhun Parmaksız
5c021bf344 chore(examples): add chart demo app (#1579)
related #1512 

Moves the chart example to apps

Co-authored-by: Josh McKinney <joshka@users.noreply.github.com>
2024-12-18 20:08:16 -08:00
Orhun Parmaksız
9721300a47 chore(examples): add canvas demo app (#1578)
related #1512 

This moves the canvas example to the apps and adds some interactivity
via changing the marker by pressing enter.
2024-12-18 20:06:12 -08:00
Orhun Parmaksız
9a541981b8 chore: make source files non-executable (#1577)
```bash
find . -type f -not -path './.git/*' -not -name '*.bash' -exec chmod 644 {} +
```

fixes #1576
2024-12-17 17:33:06 +03:00
Orhun Parmaksız
a6a1368250 chore(examples): add calendar explorer demo app (#1571)
Related to #1512 

As discussed, this moves the calendar example from ratatui to app
examples as an "explorer" example. It also adds interactivity where you
can press s to toggle between different styles of calendars.

---------

Co-authored-by: Josh McKinney <joshka@users.noreply.github.com>
2024-12-16 11:41:41 -08:00
dependabot[bot]
1fcca6369e chore(deps): bump tokio from 1.41.1 to 1.42.0 (#1574)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.41.1 to 1.42.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/tokio-rs/tokio/releases">tokio's
releases</a>.</em></p>
<blockquote>
<h2>Tokio v1.42.0</h2>
<h1>1.42.0 (Dec 3rd, 2024)</h1>
<h3>Added</h3>
<ul>
<li>io: add <code>AsyncFd::{try_io, try_io_mut}</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6967">#6967</a>)</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>io: avoid <code>ptr-&gt;ref-&gt;ptr</code> roundtrip in
RegistrationSet (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6929">#6929</a>)</li>
<li>runtime: do not defer <code>yield_now</code> inside
<code>block_in_place</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6999">#6999</a>)</li>
</ul>
<h3>Changes</h3>
<ul>
<li>io: simplify io readiness logic (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6966">#6966</a>)</li>
</ul>
<h3>Documented</h3>
<ul>
<li>net: fix docs for <code>tokio::net::unix::{pid_t, gid_t,
uid_t}</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6791">#6791</a>)</li>
<li>time: fix a typo in <code>Instant</code> docs (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6982">#6982</a>)</li>
</ul>
<p><a
href="https://redirect.github.com/tokio-rs/tokio/issues/6791">#6791</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/6791">tokio-rs/tokio#6791</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6929">#6929</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/6929">tokio-rs/tokio#6929</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6966">#6966</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/6966">tokio-rs/tokio#6966</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6967">#6967</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/6967">tokio-rs/tokio#6967</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6982">#6982</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/6982">tokio-rs/tokio#6982</a>
<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6999">#6999</a>:
<a
href="https://redirect.github.com/tokio-rs/tokio/pull/6999">tokio-rs/tokio#6999</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="bb9d57017e"><code>bb9d570</code></a>
chore: prepare Tokio v1.42.0 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7005">#7005</a>)</li>
<li><a
href="af9c683d52"><code>af9c683</code></a>
tests: fix typo in build test instructions (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7004">#7004</a>)</li>
<li><a
href="4bc5a1a058"><code>4bc5a1a</code></a>
ci: allow Unicode-3.0 license for unicode-ident (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7006">#7006</a>)</li>
<li><a
href="f8948ea021"><code>f8948ea</code></a>
runtime: do not defer <code>yield_now</code> inside
<code>block_in_place</code> (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6999">#6999</a>)</li>
<li><a
href="bce9780dd3"><code>bce9780</code></a>
time: use <code>array::from_fn</code> instead of manually creating array
(<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7000">#7000</a>)</li>
<li><a
href="38151f30cb"><code>38151f3</code></a>
readme: unlist 1.32.x as LTS release (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6997">#6997</a>)</li>
<li><a
href="5dda72d338"><code>5dda72d</code></a>
ci: pin valgrind to rustc 1.82 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6998">#6998</a>)</li>
<li><a
href="c07257f99f"><code>c07257f</code></a>
io: simplify io readiness logic (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6966">#6966</a>)</li>
<li><a
href="d08578fc9a"><code>d08578f</code></a>
time: fix a typo in <code>Instant</code> docs (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6982">#6982</a>)</li>
<li><a
href="4047d7962a"><code>4047d79</code></a>
miri: add annotations for tests with miri ignore (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6981">#6981</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/tokio-rs/tokio/compare/tokio-1.41.1...tokio-1.42.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tokio&package-manager=cargo&previous-version=1.41.1&new-version=1.42.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-16 10:26:49 -08:00
dependabot[bot]
694c788c24 chore(deps): bump serde from 1.0.215 to 1.0.216 (#1575)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.215 to
1.0.216.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/serde-rs/serde/releases">serde's
releases</a>.</em></p>
<blockquote>
<h2>v1.0.216</h2>
<ul>
<li>Mark all generated impls with #[automatically_derived] to exclude
from code coverage (<a
href="https://redirect.github.com/serde-rs/serde/issues/2866">#2866</a>,
<a
href="https://redirect.github.com/serde-rs/serde/issues/2868">#2868</a>,
thanks <a
href="https://github.com/tdittr"><code>@​tdittr</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="ad8dd4148b"><code>ad8dd41</code></a>
Release 1.0.216</li>
<li><a
href="f91d2ed9ae"><code>f91d2ed</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/serde/issues/2868">#2868</a>
from dtolnay/automaticallyderived</li>
<li><a
href="9497463718"><code>9497463</code></a>
Mark all generated trait impls as #[automatically_derived]</li>
<li><a
href="46e9ecfcdd"><code>46e9ecf</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/serde/issues/2866">#2866</a>
from tdittr/mark-visitors-as-generated</li>
<li><a
href="e9c399c822"><code>e9c399c</code></a>
Mark generated <code>impl de::Visitor</code> blocks as
<code>#[automatically_derived]</code></li>
<li><a
href="b9dbfcb4ac"><code>b9dbfcb</code></a>
Switch out fnv in favor of foldhash in test</li>
<li><a
href="c270e27a4d"><code>c270e27</code></a>
Use BuildHasher instead of Hasher in collection macros</li>
<li><a
href="0307f604ea"><code>0307f60</code></a>
Resolve question_mark clippy lint in build script</li>
<li>See full diff in <a
href="https://github.com/serde-rs/serde/compare/v1.0.215...v1.0.216">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serde&package-manager=cargo&previous-version=1.0.215&new-version=1.0.216)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-16 10:23:50 -08:00
Orhun Parmaksız
6e436725e4 docs(readme): reimagine README.md (#1569)
This is the result of the re-imagination of a more suitable README.md. It
is simpler and shorter: not giving more information to the user than
they actually need.

Also updates the quickstart code with the up-to-date version and adds
link to templates which was missing.

---------

Co-authored-by: Josh McKinney <joshka@users.noreply.github.com>
2024-12-14 22:22:33 +03:00
Orhun Parmaksız
dafb716f9d docs(widgets): add example for grouped barchart (#1566)
related #1512

---------

Co-authored-by: Josh McKinney <joshka@users.noreply.github.com>
2024-12-12 20:42:41 +03:00
Orhun Parmaksız
819e92cd44 chore(examples): add weather demo app (#1567)
related to #1512
2024-12-11 11:25:56 +03:00
dependabot[bot]
a38066d2d1 chore(deps): bump dawidd6/action-download-artifact from 6 to 7 (#1560)
Bumps
[dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact)
from 6 to 7.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/dawidd6/action-download-artifact/releases">dawidd6/action-download-artifact's
releases</a>.</em></p>
<blockquote>
<h2>v7</h2>
<h2>What's Changed</h2>
<ul>
<li>build(deps): bump fast-xml-parser from 4.4.0 to 4.4.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/dawidd6/action-download-artifact/pull/299">dawidd6/action-download-artifact#299</a></li>
<li>build(deps): bump <code>@​actions/artifact</code> from 2.1.7 to
2.1.9 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/dawidd6/action-download-artifact/pull/300">dawidd6/action-download-artifact#300</a></li>
<li>build(deps): bump adm-zip from 0.5.14 to 0.5.15 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/dawidd6/action-download-artifact/pull/301">dawidd6/action-download-artifact#301</a></li>
<li>build(deps): bump adm-zip from 0.5.15 to 0.5.16 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/dawidd6/action-download-artifact/pull/306">dawidd6/action-download-artifact#306</a></li>
<li>build(deps): bump path-to-regexp from 6.2.2 to 6.3.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/dawidd6/action-download-artifact/pull/307">dawidd6/action-download-artifact#307</a></li>
<li>build(deps): bump <code>@​actions/artifact</code> from 2.1.9 to
2.1.10 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/dawidd6/action-download-artifact/pull/311">dawidd6/action-download-artifact#311</a></li>
<li>build(deps): bump <code>@​actions/core</code> from 1.10.1 to 1.11.0
by <a href="https://github.com/dependabot"><code>@​dependabot</code></a>
in <a
href="https://redirect.github.com/dawidd6/action-download-artifact/pull/310">dawidd6/action-download-artifact#310</a></li>
<li>build(deps): bump <code>@​actions/core</code> from 1.11.0 to 1.11.1
by <a href="https://github.com/dependabot"><code>@​dependabot</code></a>
in <a
href="https://redirect.github.com/dawidd6/action-download-artifact/pull/312">dawidd6/action-download-artifact#312</a></li>
<li>build(deps): bump <code>@​actions/artifact</code> from 2.1.10 to
2.1.11 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/dawidd6/action-download-artifact/pull/313">dawidd6/action-download-artifact#313</a></li>
<li>build(deps): Fix cross-spawn &gt;=7.0.0 &lt;= 7.0.5 vulnerability by
<a href="https://github.com/alexcouret"><code>@​alexcouret</code></a> in
<a
href="https://redirect.github.com/dawidd6/action-download-artifact/pull/317">dawidd6/action-download-artifact#317</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/alexcouret"><code>@​alexcouret</code></a> made
their first contribution in <a
href="https://redirect.github.com/dawidd6/action-download-artifact/pull/317">dawidd6/action-download-artifact#317</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/dawidd6/action-download-artifact/compare/v6...v7">https://github.com/dawidd6/action-download-artifact/compare/v6...v7</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="80620a5d27"><code>80620a5</code></a>
node_modules: update</li>
<li><a
href="b15e003f46"><code>b15e003</code></a>
node_modules: install</li>
<li><a
href="1ee9a455fd"><code>1ee9a45</code></a>
build(deps): Fix cross-spawn &gt;=7.0.0 &lt;= 7.0.5 vulnerability (<a
href="https://redirect.github.com/dawidd6/action-download-artifact/issues/317">#317</a>)</li>
<li><a
href="b2f2706ac4"><code>b2f2706</code></a>
build(deps): bump <code>@​actions/artifact</code> from 2.1.10 to 2.1.11
(<a
href="https://redirect.github.com/dawidd6/action-download-artifact/issues/313">#313</a>)</li>
<li><a
href="fdbeba027c"><code>fdbeba0</code></a>
build(deps): bump <code>@​actions/core</code> from 1.11.0 to 1.11.1 (<a
href="https://redirect.github.com/dawidd6/action-download-artifact/issues/312">#312</a>)</li>
<li><a
href="a74b42987a"><code>a74b429</code></a>
build(deps): bump <code>@​actions/core</code> from 1.10.1 to 1.11.0 (<a
href="https://redirect.github.com/dawidd6/action-download-artifact/issues/310">#310</a>)</li>
<li><a
href="24e807a70c"><code>24e807a</code></a>
build(deps): bump <code>@​actions/artifact</code> from 2.1.9 to 2.1.10
(<a
href="https://redirect.github.com/dawidd6/action-download-artifact/issues/311">#311</a>)</li>
<li><a
href="9592e3c4ab"><code>9592e3c</code></a>
build(deps): bump path-to-regexp from 6.2.2 to 6.3.0 (<a
href="https://redirect.github.com/dawidd6/action-download-artifact/issues/307">#307</a>)</li>
<li><a
href="5f966b63eb"><code>5f966b6</code></a>
build(deps): bump adm-zip from 0.5.15 to 0.5.16 (<a
href="https://redirect.github.com/dawidd6/action-download-artifact/issues/306">#306</a>)</li>
<li><a
href="db9477a3eb"><code>db9477a</code></a>
build(deps): bump adm-zip from 0.5.14 to 0.5.15 (<a
href="https://redirect.github.com/dawidd6/action-download-artifact/issues/301">#301</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/dawidd6/action-download-artifact/compare/v6...v7">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dawidd6/action-download-artifact&package-manager=github_actions&previous-version=6&new-version=7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-09 15:26:49 -08:00
dependabot[bot]
3646c97840 chore(deps): bump time from 0.3.36 to 0.3.37 (#1561)
Bumps [time](https://github.com/time-rs/time) from 0.3.36 to 0.3.37.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/time-rs/time/releases">time's
releases</a>.</em></p>
<blockquote>
<h2>v0.3.37</h2>
<p>See the <a
href="https://github.com/time-rs/time/blob/main/CHANGELOG.md">changelog</a>
for details.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/time-rs/time/blob/main/CHANGELOG.md">time's
changelog</a>.</em></p>
<blockquote>
<h2>0.3.37 [2024-12-03]</h2>
<h3>Added</h3>
<ul>
<li><code>Time::MAX</code>, equivalent to
<code>time!(23:59:59.999999999)</code></li>
<li><code>[year repr:century]</code> is now supported in format
descriptions. When used in conjunction with
<code>[year repr:last_two]</code>, there is sufficient information to
parse a date. Note that with the
<code>large-date</code> feature enabled, there is an ambiguity when
parsing the two back-to-back.</li>
<li>Parsing of <code>strftime</code>-style format descriptions, located
at
<code>time::format_description::parse_strftime_borrowed</code> and
<code>time::format_description::parse_strftime_owned</code></li>
<li><code>time::util::refresh_tz</code> and
<code>time::util::refresh_tz_unchecked</code>, which updates information
obtained via the <code>TZ</code> environment variable. This is
equivalent to the <code>tzset</code> syscall on Unix-like
systems, with and without built-in soundness checks, respectively.</li>
<li><code>Month::length</code> and <code>util::days_in_month</code>,
replacing <code>util::days_in_year_month</code>.</li>
<li>Expressions are permitted in
<code>time::serde::format_description!</code> rather than only paths.
This also
drastically improves diagnostics when an invalid value is provided.</li>
</ul>
<h3>Changed</h3>
<ul>
<li>
<p>Obtaining the system UTC offset on Unix-like systems should now
succeed when multi-threaded.
However, if the <code>TZ</code> environment variable is altered, the
program will not be aware of this until
<code>time::util::refresh_tz</code> or
<code>time::util::refresh_tz_unchecked</code> is called.
<code>refresh_tz</code> has the
same soundness requirements as obtaining the system UTC offset
previously did, with the
requirements still being automatically enforced.
<code>refresh_tz_unchecked</code> does not enforce these
requirements at the expense of being <code>unsafe</code>. Most programs
should not need to call either
function.</p>
<p>Due to this change, the <code>time::util::local_offset</code> module
has been deprecated in its entirety. The
<code>get_soundness</code> and <code>set_soundness</code> functions are
now no-ops.</p>
<p>Note that while calls <em>should</em> succeed, success is not
guaranteed in any situation. Downstream
users should always be prepared to handle the error case.</p>
</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Floating point values are truncated, not rounded, when
formatting.</li>
<li>RFC3339 allows arbitrary separators between the date and time
components.</li>
<li>Serialization of negative <code>Duration</code>s less than one
second is now correct. It previously omitted
the negative sign.</li>
<li><code>From&lt;js_sys::Date&gt; for OffsetDateTime</code> now ensures
sub-millisecond values are not erroneously
returned.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="d4e39b306d"><code>d4e39b3</code></a>
v0.3.37 release</li>
<li><a
href="09439970e5"><code>0943997</code></a>
Fix CI failure</li>
<li><a
href="8b50f04ee0"><code>8b50f04</code></a>
Update lints</li>
<li><a
href="56f1db6dfa"><code>56f1db6</code></a>
Add <code>Month::length</code>, <code>days_in_month</code></li>
<li><a
href="03bcfe9f28"><code>03bcfe9</code></a>
Skip formatting some macros, update UI tests</li>
<li><a
href="4404638fe2"><code>4404638</code></a>
Permit exprs in <code>serde::format_description!</code></li>
<li><a
href="6b43b44060"><code>6b43b44</code></a>
strftime implementation</li>
<li><a
href="98569ffe5b"><code>98569ff</code></a>
Hide deprecations from docs</li>
<li><a
href="febf3a10de"><code>febf3a1</code></a>
Obtain local offset in multi-threaded situations</li>
<li><a
href="1e19827c5a"><code>1e19827</code></a>
Update rstest and rstest_reuse; bump MSRV to 1.67.1 (<a
href="https://redirect.github.com/time-rs/time/issues/716">#716</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/time-rs/time/compare/v0.3.36...v0.3.37">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=time&package-manager=cargo&previous-version=0.3.36&new-version=0.3.37)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-09 15:26:18 -08:00
dependabot[bot]
1c3b698b82 chore(deps): bump cargo_metadata from 0.19.0 to 0.19.1 (#1562)
[//]: # (dependabot-start)
⚠️  **Dependabot is rebasing this PR** ⚠️ 

Rebasing might not happen immediately, so don't worry if this takes some
time.

Note: if you make any changes to this PR yourself, they will take
precedence over the rebase.

---

[//]: # (dependabot-end)

Bumps [cargo_metadata](https://github.com/oli-obk/cargo_metadata) from
0.19.0 to 0.19.1.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/oli-obk/cargo_metadata/blob/main/CHANGELOG.md">cargo_metadata's
changelog</a>.</em></p>
<blockquote>
<h1>Changelog</h1>
<h2>Unreleased</h2>
<ul>
<li>n/a</li>
</ul>
<h3>Added</h3>
<ul>
<li>n/a</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Updated dependencies:
<ul>
<li><code>thiserror</code> from <code>1.0.31</code> to
<code>2.0.3</code></li>
<li><code>derive_builder</code> from <code>0.12</code> to
<code>0.20</code></li>
</ul>
</li>
</ul>
<h3>Removed</h3>
<ul>
<li>n/a</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>n/a</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="8f4c3a8e6d"><code>8f4c3a8</code></a>
Merge pull request <a
href="https://redirect.github.com/oli-obk/cargo_metadata/issues/276">#276</a>
from sunshowers/fromstr-display</li>
<li><a
href="e6c0f06160"><code>e6c0f06</code></a>
Merge pull request <a
href="https://redirect.github.com/oli-obk/cargo_metadata/issues/278">#278</a>
from oli-obk/push-qxuollxmvlzn</li>
<li><a
href="61ceb9aabc"><code>61ceb9a</code></a>
Pacify clippy</li>
<li><a
href="eae17fb2da"><code>eae17fb</code></a>
Bump msrv to keep in sync with our dependencies</li>
<li><a
href="2983f519a2"><code>2983f51</code></a>
add FromStr and Display impls for TargetKind and CrateType</li>
<li><a
href="834207b821"><code>834207b</code></a>
Merge pull request <a
href="https://redirect.github.com/oli-obk/cargo_metadata/issues/273">#273</a>
from regexident/update-dependencies</li>
<li><a
href="437339616a"><code>4373396</code></a>
Update dependencies</li>
<li>See full diff in <a
href="https://github.com/oli-obk/cargo_metadata/compare/0.19.0...0.19.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=cargo_metadata&package-manager=cargo&previous-version=0.19.0&new-version=0.19.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Josh McKinney <joshka@users.noreply.github.com>
2024-12-09 15:25:59 -08:00
dependabot[bot]
c767f6bc3c chore(deps): bump tokio-stream from 0.1.16 to 0.1.17 (#1563)
Bumps [tokio-stream](https://github.com/tokio-rs/tokio) from 0.1.16 to
0.1.17.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="67355c6d23"><code>67355c6</code></a>
chore: prepare tokio-stream v0.1.17 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7020">#7020</a>)</li>
<li><a
href="405d746d38"><code>405d746</code></a>
signal: remove oneshot channels from tests (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7015">#7015</a>)</li>
<li><a
href="e0d1293fac"><code>e0d1293</code></a>
ci: add instructions that explain how to fix spellcheck errors (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7016">#7016</a>)</li>
<li><a
href="480c010b01"><code>480c010</code></a>
signal: add <code>SignalKind::info</code> on illumos (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/6995">#6995</a>)</li>
<li><a
href="c032ea0203"><code>c032ea0</code></a>
ci: detect trailing whitespace (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7013">#7013</a>)</li>
<li><a
href="0b31c2f73d"><code>0b31c2f</code></a>
chore: prepare tokio-util v0.7.13 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7012">#7012</a>)</li>
<li><a
href="129f9fc0c8"><code>129f9fc</code></a>
codec: fix incorrect handling of invalid utf-8 in
<code>LinesCodec::decode_eof</code> (#...</li>
<li><a
href="b5c227d51f"><code>b5c227d</code></a>
tracing: move tracing instrumentation tests into tokio tests (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7007">#7007</a>)</li>
<li><a
href="dcae2b9eb8"><code>dcae2b9</code></a>
ci: unfreeze FreeBSD from rustc 1.81 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7009">#7009</a>)</li>
<li><a
href="bb9d57017e"><code>bb9d570</code></a>
chore: prepare Tokio v1.42.0 (<a
href="https://redirect.github.com/tokio-rs/tokio/issues/7005">#7005</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/tokio-rs/tokio/compare/tokio-stream-0.1.16...tokio-stream-0.1.17">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tokio-stream&package-manager=cargo&previous-version=0.1.16&new-version=0.1.17)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-09 15:25:05 -08:00
dependabot[bot]
08ea837753 chore(deps): bump octocrab from 0.42.0 to 0.42.1 (#1564)
Bumps [octocrab](https://github.com/XAMPPRocky/octocrab) from 0.42.0 to
0.42.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/XAMPPRocky/octocrab/releases">octocrab's
releases</a>.</em></p>
<blockquote>
<h2>v0.42.1</h2>
<h3>Other</h3>
<ul>
<li>Secret scanning alert locations API (<a
href="https://redirect.github.com/XAMPPRocky/octocrab/pull/735">#735</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/XAMPPRocky/octocrab/blob/main/CHANGELOG.md">octocrab's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/XAMPPRocky/octocrab/compare/v0.42.0...v0.42.1">0.42.1</a>
- 2024-11-22</h2>
<h3>Other</h3>
<ul>
<li>Secret scanning alert locations API (<a
href="https://redirect.github.com/XAMPPRocky/octocrab/pull/735">#735</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="653814c434"><code>653814c</code></a>
chore: release v0.42.1 (<a
href="https://redirect.github.com/XAMPPRocky/octocrab/issues/736">#736</a>)</li>
<li><a
href="592f165801"><code>592f165</code></a>
Secret scanning alert locations API (<a
href="https://redirect.github.com/XAMPPRocky/octocrab/issues/735">#735</a>)</li>
<li>See full diff in <a
href="https://github.com/XAMPPRocky/octocrab/compare/v0.42.0...v0.42.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=octocrab&package-manager=cargo&previous-version=0.42.0&new-version=0.42.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-09 15:24:47 -08:00
dependabot[bot]
a8aca0ec12 chore(deps): bump clap from 4.5.21 to 4.5.23 (#1565)
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.21 to 4.5.23.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/clap-rs/clap/releases">clap's
releases</a>.</em></p>
<blockquote>
<h2>v4.5.23</h2>
<h2>[4.5.23] - 2024-12-05</h2>
<h3>Fixes</h3>
<ul>
<li><em>(parser)</em> When check <code>allow_negative_numbers</code>,
allow <code>E</code> again</li>
</ul>
<h2>v4.5.22</h2>
<h2>[4.5.22] - 2024-12-03</h2>
<h3>Fixes</h3>
<ul>
<li><em>(assert)</em> Catch bugs with arguments requiring themself</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/clap-rs/clap/blob/master/CHANGELOG.md">clap's
changelog</a>.</em></p>
<blockquote>
<h2>[4.5.23] - 2024-12-05</h2>
<h3>Fixes</h3>
<ul>
<li><em>(parser)</em> When check <code>allow_negative_numbers</code>,
allow <code>E</code> again</li>
</ul>
<h2>[4.5.22] - 2024-12-03</h2>
<h3>Fixes</h3>
<ul>
<li><em>(assert)</em> Catch bugs with arguments requiring themself</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="7916028a90"><code>7916028</code></a>
chore: Release</li>
<li><a
href="804498d3b1"><code>804498d</code></a>
docs: Update changelog</li>
<li><a
href="f9721f1435"><code>f9721f1</code></a>
Merge pull request <a
href="https://redirect.github.com/clap-rs/clap/issues/5695">#5695</a>
from epage/value</li>
<li><a
href="b04bf72436"><code>b04bf72</code></a>
fix(complete)!: Be consistent in value language</li>
<li><a
href="0e28259e55"><code>0e28259</code></a>
chore: Release</li>
<li><a
href="e55c986309"><code>e55c986</code></a>
docs: Update changelog</li>
<li><a
href="c7157dfe1d"><code>c7157df</code></a>
Merge pull request <a
href="https://redirect.github.com/clap-rs/clap/issues/5692">#5692</a>
from epage/self</li>
<li><a
href="84252b7123"><code>84252b7</code></a>
fix(complete): Allow completing '.'</li>
<li><a
href="eded64a13b"><code>eded64a</code></a>
test(complete): Verify PathCompleter::dir</li>
<li>See full diff in <a
href="https://github.com/clap-rs/clap/compare/clap_complete-v4.5.21...clap_complete-v4.5.23">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=clap&package-manager=cargo&previous-version=4.5.21&new-version=4.5.23)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-09 15:24:05 -08:00
Orhun Parmaksız
ed5dd73084 docs(widgets): add example for tabs (#1559)
related #1512 

Also removes the tabs example from ratatui crate since it overlaps with
this new example in terms of functionality and it was not following the
general theme of other examples.
2024-12-09 15:22:03 -08:00
Josh McKinney
b5f7e44183 chore(examples): move async example to apps (#1503)
Move async example to examples/apps/async as full project.
Simplify a little by removing the need for the github api token.

Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
2024-12-09 18:30:37 +03:00
Orhun Parmaksız
fab532171d docs(widgets): add example for scrollbar (#1545)
Related to: #1512
2024-12-08 02:28:18 -08:00
Orhun Parmaksız
898aef6e2f docs(widgets): add example for list (#1542)
Related to: #1512
2024-12-08 02:27:19 -08:00
EdJoPaTo
f57b696fdc fix(span): dont render control characters (#1312) 2024-12-08 02:10:58 -08:00
Orhun Parmaksız
452366aa9e docs(widgets): add example for sparkline (#1556)
related #1512

Also removes the sparkline example from ratatui crate since this example
is a simplified and easier to understand version of that
2024-12-07 18:35:45 +03:00
Orhun Parmaksız
ff729b7607 feat(scrollbar): support retrieving the current position of state (#1552)
As of now it is possible to change the position of the Scrollbar but not
possible to retrieve the position for further use. e.g.

```rust
let mut state = ScrollbarState::default();
state.next();
```

This commit adds a new method "`current_position`" (since `position` is
already taken by the fluent setter) for that purpose:

```rust
let index = state.get_position(); // yay
```

See #1545 for the concrete usage of this.
2024-12-07 18:23:22 +03:00
Orhun Parmaksız
6ddde0e8a8 docs(widgets): add example for table (#1557)
related #1512
2024-12-07 18:21:01 +03:00
Orhun Parmaksız
93ad6b828c docs(widgets): update values in chart example (#1558)
better stonks
2024-12-07 18:20:49 +03:00
Josh McKinney
e411d9ec3e docs: add input form example (#1551)
Demonstrates how to manage the cursor and input focus with a simple
form. Uses an enum to track the current input field and passes the
input events to the active field.

This is similar to the json tutorial on the website, but a bit simpler
2024-12-05 14:12:40 -08:00
Josh McKinney
a0979d6871 chore(build): remove cargo lint (#1549)
Duplicate crate lint is too noisy and sensitive to upstream changes
2024-12-05 21:35:06 +03:00
Josh McKinney
ed071f3723 docs: add mouse-drawing example (#1546)
Demonstrates how to handle mouse events
2024-12-04 13:34:12 -08:00
Josh McKinney
9275d3421c feat(layout): add Offset::new() constructor (#1547) 2024-12-04 12:57:38 -08:00
Orhun Parmaksız
15f442a71e docs(widgets): add example for paragraph (#1544)
related #1512 

Also removes the paragraph example from `ratatui` since these examples
are more or less the same.
2024-12-04 21:16:04 +03:00
Martin Sivák
18e70d3d51 fix(crossterm): terminal should keep Bold when removing Dim (#1541)
The Dim removal should behave the same as the logic for Bold removal
that sends NormalIntensity sequence and then restores Dim when needed.

Signed-off-by: Martin Sivak <mars@montik.net>
2024-12-03 13:21:59 -08:00
Orhun Parmaksız
17bba14540 docs(widgets): move the logo example to widgets (#1543)
related #1512 

Also updates the code to make it consistent with the other examples
2024-12-03 22:30:35 +03:00
Orhun Parmaksız
ce4856a65f feat(widgets): add the missing constructor to canvas types (#1538)
Allows constructing `Rectangle`, `Points` and `Circle` using the `new`
method instead of initializing with the public fields directly.
2024-12-03 12:04:53 +03:00
Orhun Parmaksız
f2451e7f1e docs(widgets): add example for gauge (#1539)
related #1512
2024-12-03 12:04:29 +03:00
raylu
7c8573f575 refactor: rearrange selection_spacing code (#1540) 2024-12-03 00:11:47 -08:00
Orhun Parmaksız
4f0a8b21af docs(widgets): add example for canvas (#1533)
related #1512
2024-12-02 17:21:53 +03:00
Orhun Parmaksız
91147c4d75 docs(widgets): add example for chart (#1536)
stonks
2024-12-01 20:34:57 +03:00
Orhun Parmaksız
6dd25a3111 docs(widgets): add example for calendar (#1532)
related #1512
2024-12-01 14:12:06 +03:00
Josh McKinney
35eba76b4d chore(example): move demo2 to top level folder (#1524) 2024-12-01 13:46:26 +03:00
Josh McKinney
357ae7e251 chore: move terminal types to ratatui-core (#1530)
- Move Terminal, TerminalOptions, ViewPort, CompletedFrame, Frame to
  ratatui-core crate
- Move render_widget_ref() and render_stateful_widget_ref() to extension
  trait (FrameExt) due as the Ref types are unstable and kept in the
  main lib instead of -core
- Fix rustdoc errors / feature config issues

BREAKING CHANGE: to call `Frame::render_widget_ref()` or
`Frame::render_stateful_widget_ref()` you now need to import the
FrameExt trait from `ratatui::widgets` and enable the
`unstable-widget-ref` feature.

Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
2024-11-30 17:11:17 -08:00
Raffaele Cataldo
3b13240728 fix(scrollbar): check for area.is_empty() before rendering (#1529)
This adds the `area.is_empty()` back into the scrollbar render method.
Without it, the widget panics if the height is 0.

Co-authored-by: Josh McKinney <joshka@users.noreply.github.com>
2024-11-30 16:36:49 -08:00
Orhun Parmaksız
d201b8e5dd chore(xtask): check lints for only library targets (#1531)
Makes it possible to filter workspace packages by their targets.
(e.g. when we want to retrieve all the binary targets / examples, etc.)
2024-11-30 15:41:27 -08:00
Josh McKinney
21e62d84c2 chore: Move the demo example to main folder (#1523)
Add a top level examples folder for more app-ish examples
Move the demo example into the top level folder.

---------

Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
2024-11-30 03:14:19 -08:00
Josh McKinney
d3f01ebf6e chore(lint): ensure lint config is correct (#1528)
- Move lints to workspace manifest
- Add lint config to backend crates
- Fix one small lint error
2024-11-30 11:13:50 +03:00
Josh McKinney
2892bddce6 fix: rust 1.83 clippy lints (#1527)
https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
2024-11-29 10:49:12 +03:00
Josh McKinney
fbf6050c86 chore: prepare alpha modularization release (#1525)
This is the first modularization -alpha release. It captures the changes
necessary to manual publish. And ensures all the crates are properly
setup and to set a baseline for comparison in future release checks etc.

This does not update / check the git-cliff setup / changelog

Part of: #1388
2024-11-28 16:47:43 -08:00
147 changed files with 4658 additions and 3062 deletions

View File

@@ -32,17 +32,17 @@ schema_pattern = "(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)
type = "list"
name = "change_type"
choices = [
{ value = "build", name = "build: Changes that affect the build system or external dependencies (example scopes: pip, docker, npm)", key = "b" },
{ value = "chore", name = "chore: A modification that generally does not fall into any other category", key = "c" },
{ value = "ci", name = "ci: Changes to our CI configuration files and scripts (example scopes: GitLabCI)", key = "i" },
{ value = "docs", name = "docs: Documentation only changes", key = "d" },
{ value = "feat", name = "feat: A new feature.", key = "f" },
{ value = "fix", name = "fix: A bug fix.", key = "x" },
{ value = "perf", name = "perf: A code change that improves performance", key = "p" },
{ value = "refactor", name = "refactor: A code change that neither fixes a bug nor adds a feature", key = "r" },
{ value = "revert", name = "revert: Revert previous commits", key = "v" },
{ value = "style", name = "style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)", key = "s" },
{ value = "test", name = "test: Adding missing or correcting existing tests", key = "t" },
{ value = "build", name = "build: Changes that affect the build system or external dependencies (example scopes: pip, docker, npm)", key = "b" },
{ value = "chore", name = "chore: A modification that generally does not fall into any other category", key = "c" },
{ value = "ci", name = "ci: Changes to our CI configuration files and scripts (example scopes: GitLabCI)", key = "i" },
{ value = "docs", name = "docs: Documentation only changes", key = "d" },
{ value = "feat", name = "feat: A new feature.", key = "f" },
{ value = "fix", name = "fix: A bug fix.", key = "x" },
{ value = "perf", name = "perf: A code change that improves performance", key = "p" },
{ value = "refactor", name = "refactor: A code change that neither fixes a bug nor adds a feature", key = "r" },
{ value = "revert", name = "revert: Revert previous commits", key = "v" },
{ value = "style", name = "style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)", key = "s" },
{ value = "test", name = "test: Adding missing or correcting existing tests", key = "t" },
]
message = "Select the type of change you are committing"

View File

@@ -18,12 +18,12 @@ jobs:
PR_EVENT: event.json
steps:
- name: Download Benchmark Results
uses: dawidd6/action-download-artifact@v6
uses: dawidd6/action-download-artifact@v7
with:
name: ${{ env.BENCHMARK_RESULTS }}
run_id: ${{ github.event.workflow_run.id }}
- name: Download PR Event
uses: dawidd6/action-download-artifact@v6
uses: dawidd6/action-download-artifact@v7
with:
name: ${{ env.PR_EVENT }}
run_id: ${{ github.event.workflow_run.id }}

View File

@@ -28,7 +28,11 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
with: { components: rustfmt }
- run: cargo xtask lint-formatting
- uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@v2
with:
tool: taplo-cli
- run: cargo xtask format --check
# Check for typos in the codebase.
# See <https://github.com/crate-ci/typos/>
@@ -55,7 +59,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
- uses: bnjbvr/cargo-machete@v0.7.0
# Run cargo clippy.
@@ -67,7 +70,7 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
with: { components: clippy }
- uses: Swatinem/rust-cache@v2
- run: cargo xtask lint-clippy
- run: cargo xtask clippy
# Run markdownlint on all markdown files in the repository.
lint-markdown:
@@ -114,7 +117,7 @@ jobs:
with:
toolchain: ${{ matrix.toolchain }}
- uses: Swatinem/rust-cache@v2
- run: cargo xtask check
- run: cargo xtask check --all-features
# Check if README.md is up-to-date with the crate's documentation.
check-readme:
@@ -124,7 +127,7 @@ jobs:
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@cargo-rdme
- run: cargo xtask check-readme
- run: cargo xtask readme --check
# Run cargo rustdoc with the same options that would be used by docs.rs, taking into account the
# package.metadata.docs.rs configured in Cargo.toml. https://github.com/dtolnay/cargo-docs-rs
@@ -138,7 +141,7 @@ jobs:
- uses: dtolnay/rust-toolchain@nightly
- uses: dtolnay/install@cargo-docs-rs
- uses: Swatinem/rust-cache@v2
- run: cargo xtask lint-docs
- run: cargo xtask docs
# Run cargo test on the documentation of the crate. This will catch any code examples that don't
# compile, or any other issues in the documentation.

12
.taplo.toml Normal file
View File

@@ -0,0 +1,12 @@
include = ["**/*.toml"]
[formatting]
column_width = 100
reorder_keys = false
[[rule]]
include = ["**/Cargo.toml"]
keys = ["dependencies", "dev-dependencies", "build-dependencies", "workspace.dependencies"]
[rule.formatting]
reorder_keys = true

View File

@@ -12,6 +12,7 @@ This is a quick summary of the sections below:
- [Unreleased](#unreleased)
- The `From` impls for backend types are now replaced with more specific traits
- `FrameExt` trait for `unstable-widget-ref` feature
- [v0.29.0](#v0290)
- `Sparkline::data` takes `IntoIterator<Item = SparklineBar>` instead of `&[u64]` and is no longer const
- Removed public fields from `Rect` iterators
@@ -76,6 +77,28 @@ This is a quick summary of the sections below:
## Unreleased (0.30.0)
### `FrameExt` trait for `unstable-widget-ref` feature ([#1530])
[#1530]: https://github.com/ratatui/ratatui/pull/1530
To call `Frame::render_widget_ref()` or `Frame::render_stateful_widget_ref()` you now need to:
1. Import the `FrameExt` trait from `ratatui::widgets`.
2. Enable the `unstable-widget-ref` feature.
For example:
```rust
use ratatui::{
layout::Rect,
widgets::{Block, FrameExt},
};
let block = Block::new();
let area = Rect::new(0, 0, 5, 5);
frame.render_widget_ref(&block, area);
```
### `WidgetRef` no longer has a blanket implementation of Widget
Previously there was a blanket implementation of Widget for WidgetRef. This has been reversed to

View File

@@ -1,8 +1,220 @@
# Changelog
All notable changes to this project will be documented in this file.
<!-- ignore lint rules that are often triggered by content generated from commits / git-cliff -->
<!-- markdownlint-disable line-length no-bare-urls ul-style emphasis-style -->
_"Food will come, Remy. Food always comes to those who love to cook." Gusteau_
## [0.30.0-alpha.1](https://github.com/ratatui/ratatui/releases/tag/0.30.0-alpha.1) - 2025-01-14
0.30.0-alpha.1 is a pre-release of the upcoming 0.30.0 release. It is intended for testing and
feedback. Please report any issues you encounter. The primary change is that we've split the crate
into multiple crates. The main crate is now `ratatui-core` and the widgets are in `ratatui-widgets`.
This allows for widget crates to depend on a stable core crate, and for the core crate to be used
without widgets.
### Features
- [56d5e05](https://github.com/ratatui/ratatui/commit/56d5e057625378f1bdf732dabb57208453fb84d6) *(bar)* Update label and text_value to accept Into<> by @Emivvvvv in [#1471](https://github.com/ratatui/ratatui/pull/1471) [**breaking**]
- [b76ad3b](https://github.com/ratatui/ratatui/commit/b76ad3b02ea1c3381b6434c40e620f28d642948e) *(bar)* Impl Styled for Bar by @Emivvvvv in [#1476](https://github.com/ratatui/ratatui/pull/1476)
- [369b18e](https://github.com/ratatui/ratatui/commit/369b18eef2e4220147e7c7264ad7f8e023a1d2dd) *(barchart)* Reduce barchart creation verbosity by @Emivvvvv in [#1453](https://github.com/ratatui/ratatui/pull/1453)
- [9275d34](https://github.com/ratatui/ratatui/commit/9275d3421c088174bcf9de0832340bcbea76367a) *(layout)* Add Offset::new() constructor by @joshka in [#1547](https://github.com/ratatui/ratatui/pull/1547)
- [ff729b7](https://github.com/ratatui/ratatui/commit/ff729b7607e0099a155f10dfe0ce42320641b74d) *(scrollbar)* Support retrieving the current position of state by @orhun in [#1552](https://github.com/ratatui/ratatui/pull/1552)
- [ce4856a](https://github.com/ratatui/ratatui/commit/ce4856a65f3c76db714a45338ba3be9b638c6c35) *(widgets)* Add the missing constructor to canvas types by @orhun in [#1538](https://github.com/ratatui/ratatui/pull/1538)
- [50ba965](https://github.com/ratatui/ratatui/commit/50ba96518f01454cff185784a1e9676093ce06cf) *(uncategorized)* Add a new RatatuiMascot widget by @Its-Just-Nans in [#1584](https://github.com/ratatui/ratatui/pull/1584)
- [1d28c89](https://github.com/ratatui/ratatui/commit/1d28c89fe50f1a11cf1719233acca1a12d5e2d7b) *(uncategorized)* Add conversions for anstyle by @joshka in [#1581](https://github.com/ratatui/ratatui/pull/1581)
### Bug Fixes
- [860e48b](https://github.com/ratatui/ratatui/commit/860e48b0f0ec51c8596bc12985a8b37bad4fba00) *(buffer)* Buffer::get_pos() now correctly handles index > u16::MAX by @joshka in [#1447](https://github.com/ratatui/ratatui/pull/1447)
- [ec30390](https://github.com/ratatui/ratatui/commit/ec30390446b998cba97a25db63b2e3d27db7a12d) *(canvas)* Round coordinates to nearest grid cell by @joshka in [#1507](https://github.com/ratatui/ratatui/pull/1507)
- [afd1ce1](https://github.com/ratatui/ratatui/commit/afd1ce179b74f10ea786ed6f9b2999288bc94e7a) *(canvas)* Lines that start outside the visible grid are now drawn by @renesat in [#1501](https://github.com/ratatui/ratatui/pull/1501)
- [18e70d3](https://github.com/ratatui/ratatui/commit/18e70d3d51b654bb895843224edf0c21a3114dc9) *(crossterm)* Terminal should keep Bold when removing Dim by @MarSik in [#1541](https://github.com/ratatui/ratatui/pull/1541)
- [a692a6e](https://github.com/ratatui/ratatui/commit/a692a6e37114f39a3eb15b0cdc486dee8a7e91ff) *(lint)* Apply rust 1.84 clippy suggestions by @joshka in [#1612](https://github.com/ratatui/ratatui/pull/1612)
- [3b13240](https://github.com/ratatui/ratatui/commit/3b13240728597a8c459c4bb5f913372185e9df91) *(scrollbar)* Check for area.is_empty() before rendering by @farmeroy in [#1529](https://github.com/ratatui/ratatui/pull/1529)
- [f57b696](https://github.com/ratatui/ratatui/commit/f57b696fdc3bac381bccda0414400453f5abecf2) *(span)* Dont render control characters by @EdJoPaTo in [#1312](https://github.com/ratatui/ratatui/pull/1312)
- [2ce958e](https://github.com/ratatui/ratatui/commit/2ce958e38cf1ebab49b1817b669631dc349a0ebb) *(table)* Allow display of additional table row, if row height > 1 by @Lunderberg in [#1452](https://github.com/ratatui/ratatui/pull/1452)
- [2892bdd](https://github.com/ratatui/ratatui/commit/2892bddce66daf0b285a6d9f6fb3fdb2581cda2b) *(uncategorized)* Rust 1.83 clippy lints by @joshka in [#1527](https://github.com/ratatui/ratatui/pull/1527)
- [36e2d1b](https://github.com/ratatui/ratatui/commit/36e2d1bda1d8b4e1d0fbd09ba2894d56bd7eeeca) *(uncategorized)* Add feature(doc_cfg) when generating docs by @joshka in [#1506](https://github.com/ratatui/ratatui/pull/1506)
- [4d7704f](https://github.com/ratatui/ratatui/commit/4d7704fba5dcebda34c8c04bf4b5ac48e3a22008) *(uncategorized)* Make StatefulWidget and Ref work with unsized State by @thscharler in [#1505](https://github.com/ratatui/ratatui/pull/1505)
- [7b87509](https://github.com/ratatui/ratatui/commit/7b875091e18b894f53af6331a8ad5b7101a75d1e) *(uncategorized)* Typo by @marcoieni in [#1480](https://github.com/ratatui/ratatui/pull/1480)
### Refactor
- [f132fa1](https://github.com/ratatui/ratatui/commit/f132fa1715ea0893c52e35c65d505abadb75cec6) *(table)* Small readability improvements by @joshka in [#1510](https://github.com/ratatui/ratatui/pull/1510)
- [904b0aa](https://github.com/ratatui/ratatui/commit/904b0aa723e63d3fb68802b797949619506bf3a9) *(uncategorized)* Move symbols to modules by @joshka in [#1594](https://github.com/ratatui/ratatui/pull/1594)
- [7c8573f](https://github.com/ratatui/ratatui/commit/7c8573f5750ea8cf87101f81314803c834ea4942) *(uncategorized)* Rearrange selection_spacing code by @raylu in [#1540](https://github.com/ratatui/ratatui/pull/1540)
- [217c57c](https://github.com/ratatui/ratatui/commit/217c57cd60628abde1ca2f0c39b014e22c9edc4e) *(uncategorized)* Modularize backends by @orhun in [#1508](https://github.com/ratatui/ratatui/pull/1508)
- [e461b72](https://github.com/ratatui/ratatui/commit/e461b724a6b010fe242f9bd6d9746007cbf24219) *(uncategorized)* Move {Stateful,}Widget{,Ref} types into individual files by @joshka in [#1479](https://github.com/ratatui/ratatui/pull/1479)
### Documentation
- [d291042](https://github.com/ratatui/ratatui/commit/d291042e69ad930ae0d3c5d1f991d9e68320c00e) *(block)* Revise the block example by @orhun in [#1520](https://github.com/ratatui/ratatui/pull/1520)
- [fcde9cb](https://github.com/ratatui/ratatui/commit/fcde9cb9c3c5e9752fefbcc7cdeac95e2db9d684) *(changelog)* Fix typo by @orhun in [#1463](https://github.com/ratatui/ratatui/pull/1463)
- [3ae6bf1](https://github.com/ratatui/ratatui/commit/3ae6bf1d6f24407de400024dcb5924d841a2e1ba) *(contributing)* Use cargo-xtask for instructions by @orhun in [#1509](https://github.com/ratatui/ratatui/pull/1509)
- [04e1b32](https://github.com/ratatui/ratatui/commit/04e1b32cd2e77653266fa8e7269a2e08d774220e) *(layout)* Rename cassowary-rs references to cassowary by @miroim in [#1448](https://github.com/ratatui/ratatui/pull/1448)
- [088aac1](https://github.com/ratatui/ratatui/commit/088aac136d8b22557081ab4c657f5c9f5cde80d8) *(readme)* Tweak links and badges by @joshka in [#1598](https://github.com/ratatui/ratatui/pull/1598)
- [6e43672](https://github.com/ratatui/ratatui/commit/6e436725e4f8c58be527b07c464a0d8b5d306eb6) *(readme)* Reimagine README.md by @orhun in [#1569](https://github.com/ratatui/ratatui/pull/1569)
- [8f28247](https://github.com/ratatui/ratatui/commit/8f282473b21d7693f20b5f0cdad2f12b9ed209ff) *(readme)* Correct examples links by @HoKim98 in [#1484](https://github.com/ratatui/ratatui/pull/1484)
- [9f90f74](https://github.com/ratatui/ratatui/commit/9f90f7495fd46b3b7ac34160f094bc1583f82b70) *(readme)* Fix broken link by @nilsmartel in [#1485](https://github.com/ratatui/ratatui/pull/1485)
- [260af68](https://github.com/ratatui/ratatui/commit/260af68a347b527281265f7bf259eb1336aa49b2) *(readme)* Include iocraft as an alternative by @kdheepak in [#1483](https://github.com/ratatui/ratatui/pull/1483)
- [dafb716](https://github.com/ratatui/ratatui/commit/dafb716f9d8acb5dda303dc1e155dc90eb54b926) *(widgets)* Add example for grouped barchart by @orhun in [#1566](https://github.com/ratatui/ratatui/pull/1566)
- [ed5dd73](https://github.com/ratatui/ratatui/commit/ed5dd73084e2c8ccf3d36bc23048d67755a90e6a) *(widgets)* Add example for tabs by @orhun in [#1559](https://github.com/ratatui/ratatui/pull/1559)
- [fab5321](https://github.com/ratatui/ratatui/commit/fab532171d1c8e9639298550565e4eefb8737275) *(widgets)* Add example for scrollbar by @orhun in [#1545](https://github.com/ratatui/ratatui/pull/1545)
- [898aef6](https://github.com/ratatui/ratatui/commit/898aef6e2f38655e58684a2d842f03bcde0ebf0c) *(widgets)* Add example for list by @orhun in [#1542](https://github.com/ratatui/ratatui/pull/1542)
- [452366a](https://github.com/ratatui/ratatui/commit/452366aa9e666f26946ebccf6046a0bed393f5c1) *(widgets)* Add example for sparkline by @orhun in [#1556](https://github.com/ratatui/ratatui/pull/1556)
- [6ddde0e](https://github.com/ratatui/ratatui/commit/6ddde0e8a84b0909ba5631afac2dfc7878764786) *(widgets)* Add example for table by @orhun in [#1557](https://github.com/ratatui/ratatui/pull/1557)
- [93ad6b8](https://github.com/ratatui/ratatui/commit/93ad6b828c3a34be982447390d17b7953a9c328e) *(widgets)* Update values in chart example by @orhun in [#1558](https://github.com/ratatui/ratatui/pull/1558)
- [15f442a](https://github.com/ratatui/ratatui/commit/15f442a71ed4ce3faeaac3b2a3a7798940eb1846) *(widgets)* Add example for paragraph by @orhun in [#1544](https://github.com/ratatui/ratatui/pull/1544)
- [17bba14](https://github.com/ratatui/ratatui/commit/17bba14540449ae584a9cafbe2a39cc7fa451ef4) *(widgets)* Move the logo example to widgets by @orhun in [#1543](https://github.com/ratatui/ratatui/pull/1543)
- [f2451e7](https://github.com/ratatui/ratatui/commit/f2451e7f1ed1d5bd38e8901f139bc2916a4b005e) *(widgets)* Add example for gauge by @orhun in [#1539](https://github.com/ratatui/ratatui/pull/1539)
- [4f0a8b2](https://github.com/ratatui/ratatui/commit/4f0a8b21af49b825debb13695f8c1f368f4f56b5) *(widgets)* Add example for canvas by @orhun in [#1533](https://github.com/ratatui/ratatui/pull/1533)
- [91147c4](https://github.com/ratatui/ratatui/commit/91147c4d75bee207052b06a7dca4b610df321de1) *(widgets)* Add example for chart by @orhun in [#1536](https://github.com/ratatui/ratatui/pull/1536)
- [6dd25a3](https://github.com/ratatui/ratatui/commit/6dd25a311152abf3e0938c9a59e54c98e2a327a6) *(widgets)* Add example for calendar by @orhun in [#1532](https://github.com/ratatui/ratatui/pull/1532)
- [99ac005](https://github.com/ratatui/ratatui/commit/99ac005b06f807c79060dba43b33ec9b1f7c1a3a) *(widgets)* Add simple barchart example by @joshka in [#1511](https://github.com/ratatui/ratatui/pull/1511)
- [da05957](https://github.com/ratatui/ratatui/commit/da05957fa01fcc420519400d82ef9df6acace0e8) *(uncategorized)* Add widget-ref-container example by @joshka in [#1603](https://github.com/ratatui/ratatui/pull/1603)
- [1798512](https://github.com/ratatui/ratatui/commit/1798512e94b277fdfafeddb4043f7174ce2ac64a) *(uncategorized)* Fix wording in user_input example by @dawedawe in [#1611](https://github.com/ratatui/ratatui/pull/1611)
- [03066d8](https://github.com/ratatui/ratatui/commit/03066d81bfc7fb4356e8d188f3d6a15b45509c15) *(uncategorized)* Fix punctuation in canvas.rs documentation by @dawedawe in [#1583](https://github.com/ratatui/ratatui/pull/1583)
- [e411d9e](https://github.com/ratatui/ratatui/commit/e411d9ec3e921e812b7e8d2836c2ad0b60a0e6f8) *(uncategorized)* Add input form example by @joshka in [#1551](https://github.com/ratatui/ratatui/pull/1551)
- [ed071f3](https://github.com/ratatui/ratatui/commit/ed071f37232fae47a2193235d57934cc5c678baa) *(uncategorized)* Add mouse-drawing example by @joshka in [#1546](https://github.com/ratatui/ratatui/pull/1546)
- [46902f5](https://github.com/ratatui/ratatui/commit/46902f5587efe2b27c39b5e3c39109c62a636ba3) *(uncategorized)* Improve docs for workspace crates by @orhun in [#1490](https://github.com/ratatui/ratatui/pull/1490)
- [a6b5792](https://github.com/ratatui/ratatui/commit/a6b579223fd83c36e024428df49a3027cd1c21bc) *(uncategorized)* Fix example link in readme by @thomas-tacquet in [#1462](https://github.com/ratatui/ratatui/pull/1462)
### Miscellaneous Tasks
- [abe2f27](https://github.com/ratatui/ratatui/commit/abe2f273289d3798968a645a38a7a38571530065) *(backend)* Change From<T> impls to new backend specific IntoBackend and FromBackend traits by @joshka in [#1464](https://github.com/ratatui/ratatui/pull/1464) [**breaking**]
- [0a47ebd](https://github.com/ratatui/ratatui/commit/0a47ebd94bbc7a89c9e2aa893cf13a988756ec19) *(bencher)* Update bencher CLI usage by @epompeii in [#1470](https://github.com/ratatui/ratatui/pull/1470)
- [a0979d6](https://github.com/ratatui/ratatui/commit/a0979d68715b2c67b32b8909189bc103f0e81f6e) *(build)* Remove cargo lint by @joshka in [#1549](https://github.com/ratatui/ratatui/pull/1549)
- [eaa4038](https://github.com/ratatui/ratatui/commit/eaa403856ecb60338619e2e727a0388187ae017c) *(ci)* Install pre-built binaries for cargo-rdme by @orhun in [#1477](https://github.com/ratatui/ratatui/pull/1477)
- [e5e2316](https://github.com/ratatui/ratatui/commit/e5e2316451fb4c085f205b4884cc82ba8a4930e6) *(ci)* Add check for keeping README.md up-to-date by @orhun in [#1473](https://github.com/ratatui/ratatui/pull/1473)
- [2ef3583](https://github.com/ratatui/ratatui/commit/2ef3583effdeb6492d76d977177b4363129a8c8c) *(ci)* Replace cargo-make with a custom cargo-xtask by @joshka in [#1461](https://github.com/ratatui/ratatui/pull/1461)
- [98df774](https://github.com/ratatui/ratatui/commit/98df774d7f9b69a2a474d25adf38e38a428f1b77) *(core)* Move core types to ratatui-core by @joshka in [#1460](https://github.com/ratatui/ratatui/pull/1460)
- [35eba76](https://github.com/ratatui/ratatui/commit/35eba76b4dff047dde2d1e01bc427eb1b992b490) *(example)* Move demo2 to top level folder by @joshka in [#1524](https://github.com/ratatui/ratatui/pull/1524)
- [5f57d35](https://github.com/ratatui/ratatui/commit/5f57d3523436e944b60ccc7a937d69336c9f82b8) *(examples)* Add colors explorer demo app by @orhun in [#1580](https://github.com/ratatui/ratatui/pull/1580)
- [5c021bf](https://github.com/ratatui/ratatui/commit/5c021bf344b17fc4075e9663dfb270bead180e25) *(examples)* Add chart demo app by @orhun in [#1579](https://github.com/ratatui/ratatui/pull/1579)
- [9721300](https://github.com/ratatui/ratatui/commit/9721300a473096daf6b34f6cc7c13643d61a4e00) *(examples)* Add canvas demo app by @orhun in [#1578](https://github.com/ratatui/ratatui/pull/1578)
- [a6a1368](https://github.com/ratatui/ratatui/commit/a6a13682507846320a79538ffad673a58c1143f0) *(examples)* Add calendar explorer demo app by @orhun in [#1571](https://github.com/ratatui/ratatui/pull/1571)
- [819e92c](https://github.com/ratatui/ratatui/commit/819e92cd44b6bee7d21115ff465c2f3f8c82ed9b) *(examples)* Add weather demo app by @orhun in [#1567](https://github.com/ratatui/ratatui/pull/1567)
- [b5f7e44](https://github.com/ratatui/ratatui/commit/b5f7e4418364c9710d14567c73122af67e0a63ae) *(examples)* Move async example to apps by @joshka in [#1503](https://github.com/ratatui/ratatui/pull/1503)
- [17316ec](https://github.com/ratatui/ratatui/commit/17316ec5d0a4807600dd116736d66938b985e718) *(github)* Enable sponsorship button by @orhun in [#1478](https://github.com/ratatui/ratatui/pull/1478)
- [d3f01eb](https://github.com/ratatui/ratatui/commit/d3f01ebf6ea97e71bcda8c84b054943e1f24cd4e) *(lint)* Ensure lint config is correct by @joshka in [#1528](https://github.com/ratatui/ratatui/pull/1528)
- [2b7ec5c](https://github.com/ratatui/ratatui/commit/2b7ec5cb7f34edb65fc81d362d3b512b98d246ac) *(widgets)* Enable calendar widget as default by @orhun in [#1521](https://github.com/ratatui/ratatui/pull/1521)
- [d201b8e](https://github.com/ratatui/ratatui/commit/d201b8e5ddd98a1887252179dec8f09e1f342b0c) *(xtask)* Check lints for only library targets by @orhun in [#1531](https://github.com/ratatui/ratatui/pull/1531)
- [6f21319](https://github.com/ratatui/ratatui/commit/6f213191efd528fd7e0d5c99fda3e6d028ee0f98) *(uncategorized)* Rename examples with clashing names by @joshka in [#1597](https://github.com/ratatui/ratatui/pull/1597)
- [11cbb2b](https://github.com/ratatui/ratatui/commit/11cbb2ba87e557a04674973a39d59124d8683ed1) *(uncategorized)* Use cargo xtask for bacon clippy command by @joshka in [#1592](https://github.com/ratatui/ratatui/pull/1592)
- [b544e39](https://github.com/ratatui/ratatui/commit/b544e394c97fffdeddaccd44bea2214ebffa1616) *(uncategorized)* Use clap instead of argh for demo example by @joshka in [#1591](https://github.com/ratatui/ratatui/pull/1591)
- [9a54198](https://github.com/ratatui/ratatui/commit/9a541981b8accd9efe17c0893d18b520bc569b15) *(uncategorized)* Make source files non-executable by @orhun in [#1577](https://github.com/ratatui/ratatui/pull/1577)
- [357ae7e](https://github.com/ratatui/ratatui/commit/357ae7e251721f2e7fcb539de5e6fc60eaa30e29) *(uncategorized)* Move terminal types to ratatui-core by @joshka in [#1530](https://github.com/ratatui/ratatui/pull/1530) [**breaking**]
- [21e62d8](https://github.com/ratatui/ratatui/commit/21e62d84c2d2fa2d5563caf0c0974c2514e56ee5) *(uncategorized)* Move the demo example to main folder by @joshka in [#1523](https://github.com/ratatui/ratatui/pull/1523)
- [fbf6050](https://github.com/ratatui/ratatui/commit/fbf6050c867b63276ae3d6f5bca4d741c2ce355c) *(uncategorized)* Prepare alpha modularization release by @joshka in [#1525](https://github.com/ratatui/ratatui/pull/1525)
- [e4e95bc](https://github.com/ratatui/ratatui/commit/e4e95bcecf15deb09416a0e53193d261f012222a) *(uncategorized)* Remove --color always flags from bacon.toml by @joshka in [#1502](https://github.com/ratatui/ratatui/pull/1502)
- [a41c97b](https://github.com/ratatui/ratatui/commit/a41c97b413b28d0db6d1ea09dcc1d5b8556148b1) *(uncategorized)* Move unstable widget refs to ratatui by @joshka in [#1491](https://github.com/ratatui/ratatui/pull/1491) [**breaking**]
- [e7085e3](https://github.com/ratatui/ratatui/commit/e7085e3a3ec4b3b90a4e69d49add96e7ba65616c) *(uncategorized)* Move widgets into ratatui-widgets crate by @joshka in [#1474](https://github.com/ratatui/ratatui/pull/1474)
- [f1d0a18](https://github.com/ratatui/ratatui/commit/f1d0a1837564d69f00e4b5d9eb94cc001cd3a3a7) *(uncategorized)* Move ratatui crate into workspace folder by @joshka in [#1459](https://github.com/ratatui/ratatui/pull/1459)
- [55fb2d2](https://github.com/ratatui/ratatui/commit/55fb2d2e56b492f0f4131fde9d44951b504cf50c) *(uncategorized)* Update repo links to ratatui instead of ratatui-org by @joshka in [#1458](https://github.com/ratatui/ratatui/pull/1458)
### Continuous Integration
- [4a871f9](https://github.com/ratatui/ratatui/commit/4a871f993ea38069da513660707a072be299b791) *(uncategorized)* Refactor xtask / toml formatting by @joshka in [#1602](https://github.com/ratatui/ratatui/pull/1602)
### New Contributors
* @dawedawe made their first contribution in [#1611](https://github.com/ratatui/ratatui/pull/1611)
* @Its-Just-Nans made their first contribution in [#1584](https://github.com/ratatui/ratatui/pull/1584)
* @MarSik made their first contribution in [#1541](https://github.com/ratatui/ratatui/pull/1541)
* @raylu made their first contribution in [#1540](https://github.com/ratatui/ratatui/pull/1540)
* @renesat made their first contribution in [#1501](https://github.com/ratatui/ratatui/pull/1501)
* @HoKim98 made their first contribution in [#1484](https://github.com/ratatui/ratatui/pull/1484)
* @nilsmartel made their first contribution in [#1485](https://github.com/ratatui/ratatui/pull/1485)
* @marcoieni made their first contribution in [#1480](https://github.com/ratatui/ratatui/pull/1480)
* @epompeii made their first contribution in [#1470](https://github.com/ratatui/ratatui/pull/1470)
* @thomas-tacquet made their first contribution in [#1462](https://github.com/ratatui/ratatui/pull/1462)
* @miroim made their first contribution in [#1448](https://github.com/ratatui/ratatui/pull/1448)
**Full Changelog**: https://github.com/ratatui/ratatui/compare/v0.29.0...0.30.0-alpha.1
## [v0.29.0](https://github.com/ratatui/ratatui/releases/tag/v0.29.0) - 2024-10-21
> _"Food will come, Remy. Food always comes to those who love to cook."_ Gusteau
We are excited to announce the new version of `ratatui` - a Rust library that's all about cooking up TUIs 👨‍🍳🐀
@@ -10,8 +222,6 @@ We are excited to announce the new version of `ratatui` - a Rust library that's
⚠️ List of breaking changes can be found [here](https://github.com/ratatui/ratatui/blob/main/BREAKING-CHANGES.md).
## [v0.29.0](https://github.com/ratatui/ratatui/releases/tag/v0.29.0) - 2024-10-21
### Features
- [3a43274](https://github.com/ratatui/ratatui/commit/3a43274881a79b4e593536c2ca915b509e557215) *(color)* Add hsluv support by @du-ob in [#1333](https://github.com/ratatui/ratatui/pull/1333)
@@ -433,6 +643,7 @@ We are excited to announce the new version of `ratatui` - a Rust library that's
> <https://github.com/ratatui/ratatui/issues/738>
>
> To update your code:
>
> ```rust
>
> Block::new().title(Title::from("foo"));
@@ -483,17 +694,18 @@ We are excited to announce the new version of `ratatui` - a Rust library that's
> Given:```rust
>
> Text::from_iter([
> Line::from("without line fields"),
> Line::from("with line fields").bold().centered(),
> Line::from_iter([
> Span::from("without span fields"),
> Span::from("with span fields")
> .green()
> .on_black()
> .italic()
> .not_dim(),
> ]),
> Line::from("without line fields"),
> Line::from("with line fields").bold().centered(),
> Line::from_iter([
> Span::from("without span fields"),
> Span::from("with span fields")
> .green()
> .on_black()
> .italic()
> .not_dim(),
> ]),
> ])
>
> ```
>
> Debug:```

689
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,15 @@
[workspace]
resolver = "2"
members = ["ratatui", "ratatui-*", "xtask"]
members = ["ratatui", "ratatui-*", "xtask", "examples/apps/*"]
default-members = [
"ratatui",
"ratatui-core",
"ratatui-crossterm",
# this is not included as it doesn't compile on windows
# "ratatui-termion",
"ratatui-termwiz",
"ratatui-widgets",
"ratatui",
"ratatui-core",
"ratatui-crossterm",
# this is not included as it doesn't compile on windows
# "ratatui-termion",
"ratatui-termwiz",
"ratatui-widgets",
"examples/apps/*",
]
[workspace.package]
@@ -25,31 +26,72 @@ edition = "2021"
rust-version = "1.74.0"
[workspace.dependencies]
bitflags = "2.6.0"
bitflags = "2.7.0"
color-eyre = "0.6.3"
crossterm = "0.28.1"
document-features = "0.2.7"
indoc = "2.0.5"
instability = "0.3.3"
instability = "0.3.7"
itertools = "0.13.0"
pretty_assertions = "1.4.1"
ratatui = { path = "ratatui", version = "0.30.0-alpha.0" }
ratatui-core = { path = "ratatui-core", version = "0.1.0-alpha.0" }
ratatui-crossterm = { path = "ratatui-crossterm", version = "0.1.0-alpha.0" }
ratatui-termion = { path = "ratatui-termion", version = "0.1.0-alpha.0" }
ratatui-termwiz = { path = "ratatui-termwiz", version = "0.1.0-alpha.0" }
ratatui-widgets = { path = "ratatui-widgets", version = "0.3.0-alpha.0" }
rstest = "0.23.0"
serde = { version = "1.0.215", features = ["derive"] }
serde_json = "1.0.133"
ratatui = { path = "ratatui", version = "0.30.0-alpha.1" }
ratatui-core = { path = "ratatui-core", version = "0.1.0-alpha.2" }
ratatui-crossterm = { path = "ratatui-crossterm", version = "0.1.0-alpha.1" }
ratatui-termion = { path = "ratatui-termion", version = "0.1.0-alpha.1" }
ratatui-termwiz = { path = "ratatui-termwiz", version = "0.1.0-alpha.1" }
ratatui-widgets = { path = "ratatui-widgets", version = "0.3.0-alpha.1" }
rstest = "0.24.0"
serde = { version = "1.0.217", features = ["derive"] }
serde_json = "1.0.135"
strum = { version = "0.26.3", features = ["derive"] }
termwiz = { version = "0.22.0" }
unicode-segmentation = "1.12.0"
# See <https://github.com/ratatui/ratatui/issues/1271> for information about why we pin unicode-width
unicode-width = "=0.2.0"
termion = "4.0.0"
unicode-width = "=0.2.0"
# Improve benchmark consistency
[profile.bench]
codegen-units = 1
lto = true
[workspace.lints.rust]
unsafe_code = "forbid"
[workspace.lints.clippy]
pedantic = { level = "warn", priority = -1 }
cast_possible_truncation = "allow"
cast_possible_wrap = "allow"
cast_precision_loss = "allow"
cast_sign_loss = "allow"
missing_errors_doc = "allow"
missing_panics_doc = "allow"
module_name_repetitions = "allow"
must_use_candidate = "allow"
# we often split up a module into multiple files with the main type in a file named after the
# module, so we want to allow this pattern
module_inception = "allow"
# nursery or restricted
as_underscore = "warn"
deref_by_slicing = "warn"
else_if_without_else = "warn"
empty_line_after_doc_comments = "warn"
equatable_if_let = "warn"
fn_to_numeric_cast_any = "warn"
format_push_string = "warn"
map_err_ignore = "warn"
missing_const_for_fn = "warn"
mixed_read_write_in_expression = "warn"
mod_module_files = "warn"
needless_pass_by_ref_mut = "warn"
needless_raw_strings = "warn"
or_fun_call = "warn"
redundant_type_annotations = "warn"
rest_pat_in_fully_bound_structs = "warn"
string_lit_chars_any = "warn"
string_slice = "warn"
string_to_string = "warn"
unnecessary_self_imports = "warn"
use_self = "warn"

444
README.md
View File

@@ -1,380 +1,170 @@
<details>
<summary>Table of Contents</summary>
- [Ratatui](#ratatui)
- [Quick Start](#quickstart)
- [Other documentation](#other-documentation)
- [Introduction](#introduction)
- [Quickstart](#quickstart)
- [Initialize and restore the terminal](#initialize-and-restore-the-terminal)
- [Drawing the UI](#drawing-the-ui)
- [Handling events](#handling-events)
- [Layout](#layout)
- [Text and styling](#text-and-styling)
- [Status of this fork](#status-of-this-fork)
- [Widgets](#widgets)
- [Built in](#built-in)
- [Third-party libraries, bootstrapping templates and widgets](#third-party-libraries-bootstrapping-templates-and-widgets)
- [Apps](#apps)
- [Alternatives](#alternatives)
- [Acknowledgments](#acknowledgments)
- [License](#license)
- [Quickstart](#quickstart)
- [Documentation](#documentation)
- [Templates](#templates)
- [Built with Ratatui](#built-with-ratatui)
- [Alternatives](#alternatives)
- [Contributing](#contributing)
- [Acknowledgements](#acknowledgements)
- [License](#license)
</details>
<!-- cargo-rdme start -->
![Demo](https://github.com/ratatui/ratatui/blob/87ae72dbc756067c97f6400d3e2a58eeb383776e/examples/demo2-destroy.gif?raw=true)
<div align="center">
[![Crate Badge]][Crate] [![Docs Badge]][API Docs] [![CI Badge]][CI Workflow] [![Deps.rs
Badge]][Deps.rs]<br> [![Codecov Badge]][Codecov] [![License Badge]](./LICENSE) [![Sponsors
Badge]][GitHub Sponsors]<br> [![Discord Badge]][Discord Server] [![Matrix Badge]][Matrix]
[![Forum Badge]][Forum]<br>
[Ratatui Website] · [API Docs] · [Examples] · [Changelog] · [Breaking Changes]<br>
[Contributing] · [Report a bug] · [Request a Feature] · [Create a Pull Request]
[![Crate Badge]][Crate] [![Repo Badge]][Repo] [![Docs Badge]][Docs] [![License Badge]][License] \
[![CI Badge]][CI] [![Deps Badge]][Deps] [![Codecov Badge]][Codecov] [![Sponsors Badge]][Sponsors] \
[Ratatui Website] · [Docs] · [Widget Examples] · [App Examples] · [Changelog] \
[Breaking Changes] · [Contributing] · [Report a bug] · [Request a Feature]
</div>
# Ratatui
[Ratatui][Ratatui Website] is a crate for cooking up terminal user interfaces in Rust. It is a
lightweight library that provides a set of widgets and utilities to build complex Rust TUIs.
Ratatui was forked from the [tui-rs] crate in 2023 in order to continue its development.
[Ratatui][Ratatui Website] (_ˌræ.təˈtu.i_) is a Rust crate for cooking up terminal user interfaces
(TUIs). It provides a simple and flexible way to create text-based user interfaces in the terminal,
which can be used for command-line applications, dashboards, and other interactive console programs.
## Quickstart
Add `ratatui` and `crossterm` as dependencies to your cargo.toml:
Ratatui has [templates] available to help you get started quickly. You can use the
[`cargo-generate`] command to create a new project with Ratatui:
```shell
cargo add ratatui crossterm
cargo install --locked cargo-generate
cargo generate ratatui/templates
```
Then you can create a simple "Hello World" application:
Selecting the Hello World template produces the following application:
```rust
use color_eyre::Result;
use crossterm::event::{self, Event};
use ratatui::{text::Text, Frame};
use ratatui::{DefaultTerminal, Frame};
fn main() {
let mut terminal = ratatui::init();
loop {
terminal.draw(draw).expect("failed to draw frame");
if matches!(event::read().expect("failed to read event"), Event::Key(_)) {
break;
}
}
ratatui::restore();
}
fn draw(frame: &mut Frame) {
let text = Text::raw("Hello World!");
frame.render_widget(text, frame.area());
}
```
The full code for this example which contains a little more detail is in the [Examples]
directory. For more guidance on different ways to structure your application see the
[Application Patterns] and [Hello World tutorial] sections in the [Ratatui Website] and the
various [Examples]. There are also several starter templates available in the [templates]
repository.
## Other documentation
- [Ratatui Website] - explains the library's concepts and provides step-by-step tutorials
- [Ratatui Forum][Forum] - a place to ask questions and discuss the library
- [API Docs] - the full API documentation for the library on docs.rs.
- [Examples] - a collection of examples that demonstrate how to use the library.
- [Contributing] - Please read this if you are interested in contributing to the project.
- [Changelog] - generated by [git-cliff] utilizing [Conventional Commits].
- [Breaking Changes] - a list of breaking changes in the library.
You can also watch the [FOSDEM 2024 talk] about Ratatui which gives a brief introduction to
terminal user interfaces and showcases the features of Ratatui, along with a hello world demo.
## Introduction
Ratatui is based on the principle of immediate rendering with intermediate buffers. This means
that for each frame, your app must render all widgets that are supposed to be part of the UI.
This is in contrast to the retained mode style of rendering where widgets are updated and then
automatically redrawn on the next frame. See the [Rendering] section of the [Ratatui Website]
for more info.
Ratatui uses [Crossterm] by default as it works on most platforms. See the [Installation]
section of the [Ratatui Website] for more details on how to use other backends ([Termion] /
[Termwiz]).
Every application built with `ratatui` needs to implement the following steps:
- Initialize the terminal
- A main loop that:
- Draws the UI
- Handles input events
- Restore the terminal state
### Initialize and restore the terminal
The [`Terminal`] type is the main entry point for any Ratatui application. It is generic over a
a choice of [`Backend`] implementations that each provide functionality to draw frames, clear
the screen, hide the cursor, etc. There are backend implementations for [Crossterm], [Termion]
and [Termwiz].
The simplest way to initialize the terminal is to use the [`init`] function which returns a
[`DefaultTerminal`] instance with the default options, enters the Alternate Screen and Raw mode
and sets up a panic hook that restores the terminal in case of panic. This instance can then be
used to draw frames and interact with the terminal state. (The [`DefaultTerminal`] instance is a
type alias for a terminal with the [`crossterm`] backend.) The [`restore`] function restores the
terminal to its original state.
```rust
fn main() -> std::io::Result<()> {
let mut terminal = ratatui::init();
let result = run(&mut terminal);
fn main() -> Result<()> {
color_eyre::install()?;
let terminal = ratatui::init();
let result = run(terminal);
ratatui::restore();
result
}
```
See the [`backend` module] and the [Backends] section of the [Ratatui Website] for more info on
the alternate screen and raw mode.
### Drawing the UI
Drawing the UI is done by calling the [`Terminal::draw`] method on the terminal instance. This
method takes a closure that is called with a [`Frame`] instance. The [`Frame`] provides the size
of the area to draw to and allows the app to render any [`Widget`] using the provided
[`render_widget`] method. After this closure returns, a diff is performed and only the changes
are drawn to the terminal. See the [Widgets] section of the [Ratatui Website] for more info.
The closure passed to the [`Terminal::draw`] method should handle the rendering of a full frame.
```rust
use ratatui::{widgets::Paragraph, Frame};
fn run(terminal: &mut ratatui::DefaultTerminal) -> std::io::Result<()> {
fn run(mut terminal: DefaultTerminal) -> Result<()> {
loop {
terminal.draw(|frame| draw(frame))?;
if handle_events()? {
terminal.draw(render)?;
if matches!(event::read()?, Event::Key(_)) {
break Ok(());
}
}
}
fn draw(frame: &mut Frame) {
let text = Paragraph::new("Hello World!");
frame.render_widget(text, frame.area());
fn render(frame: &mut Frame) {
frame.render_widget("hello world", frame.area());
}
```
### Handling events
## Documentation
Ratatui does not include any input handling. Instead event handling can be implemented by
calling backend library methods directly. See the [Handling Events] section of the [Ratatui
Website] for more info. For example, if you are using [Crossterm], you can use the
[`crossterm::event`] module to handle events.
- [Docs] - the full API documentation for the library on docs.rs.
- [Ratatui Website] - explains the library's concepts and provides step-by-step tutorials.
- [Ratatui Forum] - a place to ask questions and discuss the library.
- [Widget Examples] - a collection of examples that demonstrate how to use the library.
- [App Examples] - a collection of more complex examples that demonstrate how to build apps.
- [Changelog] - generated by [git-cliff] utilizing [Conventional Commits].
- [Breaking Changes] - a list of breaking changes in the library.
```rust
use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind};
You can also watch the [EuroRust 2024 talk] to learn about common concepts in Ratatui and what's
possible to build with it.
fn handle_events() -> std::io::Result<bool> {
match event::read()? {
Event::Key(key) if key.kind == KeyEventKind::Press => match key.code {
KeyCode::Char('q') => return Ok(true),
// handle other key events
_ => {}
},
// handle other events
_ => {}
}
Ok(false)
}
## Templates
If you're looking to get started quickly, you can use one of the available templates from the
[templates] repository using [`cargo-generate`]:
```shell
cargo generate ratatui/templates
```
## Layout
The library comes with a basic yet useful layout management object called [`Layout`] which
allows you to split the available space into multiple areas and then render widgets in each
area. This lets you describe a responsive terminal UI by nesting layouts. See the [Layout]
section of the [Ratatui Website] for more info.
```rust
use ratatui::{
layout::{Constraint, Layout},
widgets::Block,
Frame,
};
fn draw(frame: &mut Frame) {
use Constraint::{Fill, Length, Min};
let vertical = Layout::vertical([Length(1), Min(0), Length(1)]);
let [title_area, main_area, status_area] = vertical.areas(frame.area());
let horizontal = Layout::horizontal([Fill(1); 2]);
let [left_area, right_area] = horizontal.areas(main_area);
frame.render_widget(Block::bordered().title("Title Bar"), title_area);
frame.render_widget(Block::bordered().title("Status Bar"), status_area);
frame.render_widget(Block::bordered().title("Left"), left_area);
frame.render_widget(Block::bordered().title("Right"), right_area);
}
```
Running this example produces the following output:
```text
Title Bar───────────────────────────────────
┌Left────────────────┐┌Right───────────────┐
│ ││ │
└────────────────────┘└────────────────────┘
Status Bar──────────────────────────────────
```
## Text and styling
The [`Text`], [`Line`] and [`Span`] types are the building blocks of the library and are used in
many places. [`Text`] is a list of [`Line`]s and a [`Line`] is a list of [`Span`]s. A [`Span`]
is a string with a specific style.
The [`style` module] provides types that represent the various styling options. The most
important one is [`Style`] which represents the foreground and background colors and the text
attributes of a [`Span`]. The [`style` module] also provides a [`Stylize`] trait that allows
short-hand syntax to apply a style to widgets and text. See the [Styling Text] section of the
[Ratatui Website] for more info.
```rust
use ratatui::{
layout::{Constraint, Layout},
style::{Color, Modifier, Style, Stylize},
text::{Line, Span},
widgets::{Block, Paragraph},
Frame,
};
fn draw(frame: &mut Frame) {
let areas = Layout::vertical([Constraint::Length(1); 4]).split(frame.area());
let line = Line::from(vec![
Span::raw("Hello "),
Span::styled(
"World",
Style::new()
.fg(Color::Green)
.bg(Color::White)
.add_modifier(Modifier::BOLD),
),
"!".red().on_light_yellow().italic(),
]);
frame.render_widget(line, areas[0]);
// using the short-hand syntax and implicit conversions
let paragraph = Paragraph::new("Hello World!".red().on_white().bold());
frame.render_widget(paragraph, areas[1]);
// style the whole widget instead of just the text
let paragraph = Paragraph::new("Hello World!").style(Style::new().red().on_white());
frame.render_widget(paragraph, areas[2]);
// use the simpler short-hand syntax
let paragraph = Paragraph::new("Hello World!").blue().on_yellow();
frame.render_widget(paragraph, areas[3]);
}
```
[Ratatui Website]: https://ratatui.rs/
[Installation]: https://ratatui.rs/installation/
[Rendering]: https://ratatui.rs/concepts/rendering/
[Application Patterns]: https://ratatui.rs/concepts/application-patterns/
[Hello World tutorial]: https://ratatui.rs/tutorials/hello-world/
[Backends]: https://ratatui.rs/concepts/backends/
[Widgets]: https://ratatui.rs/how-to/widgets/
[Handling Events]: https://ratatui.rs/concepts/event-handling/
[Layout]: https://ratatui.rs/how-to/layout/
[Styling Text]: https://ratatui.rs/how-to/render/style-text/
[templates]: https://github.com/ratatui/templates/
[Examples]: https://github.com/ratatui/ratatui/tree/main/ratatui/examples/README.md
[Report a bug]: https://github.com/ratatui/ratatui/issues/new?labels=bug&projects=&template=bug_report.md
[Request a Feature]: https://github.com/ratatui/ratatui/issues/new?labels=enhancement&projects=&template=feature_request.md
[Create a Pull Request]: https://github.com/ratatui/ratatui/compare
[git-cliff]: https://git-cliff.org
[Conventional Commits]: https://www.conventionalcommits.org
[API Docs]: https://docs.rs/ratatui
[Changelog]: https://github.com/ratatui/ratatui/blob/main/CHANGELOG.md
[Contributing]: https://github.com/ratatui/ratatui/blob/main/CONTRIBUTING.md
[Breaking Changes]: https://github.com/ratatui/ratatui/blob/main/BREAKING-CHANGES.md
[FOSDEM 2024 talk]: https://www.youtube.com/watch?v=NU0q6NOLJ20
[`Frame`]: terminal::Frame
[`render_widget`]: terminal::Frame::render_widget
[`Widget`]: widgets::Widget
[`Layout`]: layout::Layout
[`Text`]: text::Text
[`Line`]: text::Line
[`Span`]: text::Span
[`Style`]: style::Style
[`style` module]: style
[`Stylize`]: style::Stylize
[`Backend`]: backend::Backend
[`backend` module]: backend
[`crossterm::event`]: https://docs.rs/crossterm/latest/crossterm/event/index.html
[Crate]: https://crates.io/crates/ratatui
[Crossterm]: https://crates.io/crates/crossterm
[Termion]: https://crates.io/crates/termion
[Termwiz]: https://crates.io/crates/termwiz
[tui-rs]: https://crates.io/crates/tui
[GitHub Sponsors]: https://github.com/sponsors/ratatui
[Crate Badge]: https://img.shields.io/crates/v/ratatui?logo=rust&style=flat-square&logoColor=E05D44&color=E05D44
[License Badge]: https://img.shields.io/crates/l/ratatui?style=flat-square&color=1370D3
[CI Badge]: https://img.shields.io/github/actions/workflow/status/ratatui/ratatui/ci.yml?style=flat-square&logo=github
[CI Workflow]: https://github.com/ratatui/ratatui/actions/workflows/ci.yml
[Codecov Badge]: https://img.shields.io/codecov/c/github/ratatui/ratatui?logo=codecov&style=flat-square&token=BAQ8SOKEST&color=C43AC3&logoColor=C43AC3
[Codecov]: https://app.codecov.io/gh/ratatui/ratatui
[Deps.rs Badge]: https://deps.rs/repo/github/ratatui/ratatui/status.svg?style=flat-square
[Deps.rs]: https://deps.rs/repo/github/ratatui/ratatui
[Discord Badge]: https://img.shields.io/discord/1070692720437383208?label=discord&logo=discord&style=flat-square&color=1370D3&logoColor=1370D3
[Discord Server]: https://discord.gg/pMCEU9hNEj
[Docs Badge]: https://img.shields.io/docsrs/ratatui?logo=rust&style=flat-square&logoColor=E05D44
[Matrix Badge]: https://img.shields.io/matrix/ratatui-general%3Amatrix.org?style=flat-square&logo=matrix&label=Matrix&color=C43AC3
[Matrix]: https://matrix.to/#/#ratatui:matrix.org
[Forum Badge]: https://img.shields.io/discourse/likes?server=https%3A%2F%2Fforum.ratatui.rs&style=flat-square&logo=discourse&label=forum&color=C43AC3
[Forum]: https://forum.ratatui.rs
[Sponsors Badge]: https://img.shields.io/github/sponsors/ratatui?logo=github&style=flat-square&color=1370D3
<!-- cargo-rdme end -->
## Contributing
In order to organize ourselves, we currently use a [Discord server](https://discord.gg/pMCEU9hNEj),
feel free to join and come chat! There is also a [Matrix](https://matrix.org/) bridge available at
[#ratatui:matrix.org](https://matrix.to/#/#ratatui:matrix.org).
We have also recently launched the [Ratatui Forum][Forum], For bugs and features, we rely on GitHub.
Please [Report a bug], [Request a Feature] or [Create a Pull Request].
Please make sure you read the [contributing](./CONTRIBUTING.md) guidelines, especially if you are
interested in working on a PR or issue opened in the previous repository.
## Built with Ratatui
Ratatui has a number of built-in [widgets](https://docs.rs/ratatui/latest/ratatui/widgets/), as well
as many contributed by external contributors. Check out the [Showcase](https://ratatui.rs/showcase/)
section of the website, or the [awesome-ratatui](https://github.com/ratatui/awesome-ratatui) repo
for a curated list of awesome apps/libraries built with `ratatui`!
[![Awesome](https://awesome.re/badge-flat2.svg)][awesome-ratatui]
Check out the [showcase] section of the website, or the [awesome-ratatui] repository for a curated
list of awesome apps and libraries built with Ratatui!
## Alternatives
You might want to checkout [Cursive](https://github.com/gyscos/Cursive) or
[iocraft](https://github.com/ccbrown/iocraft/) for an alternative solutions
to build text user interfaces in Rust.
- [Cursive](https://crates.io/crates/cursive) - a ncurses-based TUI library.
- [iocraft](https://crates.io/crates/iocraft) - a declarative TUI library.
## Acknowledgments
## Contributing
None of this could be possible without [**Florian Dehau**](https://github.com/fdehau) who originally
created [tui-rs] which inspired many Rust TUIs.
[![Discord Badge]][Discord Server] [![Matrix Badge]][Matrix] [![Forum Badge]][Ratatui Forum]
Special thanks to [**Pavel Fomchenkov**](https://github.com/nawok) for his work in designing **an
awesome logo** for the ratatui project and ratatui organization.
Feel free to join our [Discord server](https://discord.gg/pMCEU9hNEj) for discussions and questions!
There is also a [Matrix](https://matrix.org/) bridge available at
[#ratatui:matrix.org](https://matrix.to/#/#ratatui:matrix.org). We have also recently launched the
[Ratatui Forum].
We rely on GitHub for [bugs][Report a bug] and [feature requests][Request a Feature].
Please make sure you read the [contributing](./CONTRIBUTING.md) guidelines before [creating a pull
request][Create a Pull Request].
## Acknowledgements
Ratatui was forked from the [tui-rs] crate in 2023 in order to continue its development. None of
this could be possible without [Florian Dehau] who originally created [tui-rs] which inspired many
Rust TUIs.
Special thanks to [Pavel Fomchenkov] for his work in designing an awesome logo for the Ratatui
project and organization.
## License
[MIT](./LICENSE)
This project is licensed under the [MIT License][License].
[Repo]: https://github.com/ratatui/ratatui
[Ratatui Website]: https://ratatui.rs/
[Ratatui Forum]: https://forum.ratatui.rs
[Docs]: https://docs.rs/ratatui
[Widget Examples]: https://github.com/ratatui/ratatui/tree/main/ratatui-widgets/examples
[App Examples]: https://github.com/ratatui/ratatui/tree/main/examples
[Changelog]: https://github.com/ratatui/ratatui/blob/main/CHANGELOG.md
[git-cliff]: https://git-cliff.org
[Conventional Commits]: https://www.conventionalcommits.org
[Breaking Changes]: https://github.com/ratatui/ratatui/blob/main/BREAKING-CHANGES.md
[EuroRust 2024 talk]: https://www.youtube.com/watch?v=hWG51Mc1DlM
[Report a bug]: https://github.com/ratatui/ratatui/issues/new?labels=bug&projects=&template=bug_report.md
[Request a Feature]: https://github.com/ratatui/ratatui/issues/new?labels=enhancement&projects=&template=feature_request.md
[Create a Pull Request]: https://github.com/ratatui/ratatui/compare
[Contributing]: https://github.com/ratatui/ratatui/blob/main/CONTRIBUTING.md
[Crate]: https://crates.io/crates/ratatui
[tui-rs]: https://crates.io/crates/tui
[Sponsors]: https://github.com/sponsors/ratatui
[Crate Badge]: https://img.shields.io/crates/v/ratatui?logo=rust&style=flat-square&color=E05D44
[Repo Badge]: https://img.shields.io/badge/repo-ratatui/ratatui-1370D3?style=flat-square&logo=github
[License Badge]: https://img.shields.io/crates/l/ratatui?style=flat-square&color=1370D3
[CI Badge]: https://img.shields.io/github/actions/workflow/status/ratatui/ratatui/ci.yml?style=flat-square&logo=github
[CI]: https://github.com/ratatui/ratatui/actions/workflows/ci.yml
[Codecov Badge]: https://img.shields.io/codecov/c/github/ratatui/ratatui?logo=codecov&style=flat-square&token=BAQ8SOKEST&color=C43AC3
[Codecov]: https://app.codecov.io/gh/ratatui/ratatui
[Deps Badge]: https://deps.rs/repo/github/ratatui/ratatui/status.svg?path=ratatui&style=flat-square
[Deps]: https://deps.rs/repo/github/ratatui/ratatui?path=ratatui
[Discord Badge]: https://img.shields.io/discord/1070692720437383208?label=discord&logo=discord&style=flat-square&color=1370D3&logoColor=1370D3
[Discord Server]: https://discord.gg/pMCEU9hNEj
[Docs Badge]: https://img.shields.io/badge/docs-ratatui-1370D3?style=flat-square&logo=rust
[Matrix Badge]: https://img.shields.io/matrix/ratatui-general%3Amatrix.org?style=flat-square&logo=matrix&label=Matrix&color=C43AC3
[Matrix]: https://matrix.to/#/#ratatui:matrix.org
[Forum Badge]: https://img.shields.io/discourse/likes?server=https%3A%2F%2Fforum.ratatui.rs&style=flat-square&logo=discourse&label=forum&color=C43AC3
[Sponsors Badge]: https://img.shields.io/github/sponsors/ratatui?logo=github&style=flat-square&color=1370D3
[templates]: https://github.com/ratatui/templates/
[showcase]: https://ratatui.rs/showcase/
[awesome-ratatui]: https://github.com/ratatui/awesome-ratatui
[Pavel Fomchenkov]: https://github.com/nawok
[Florian Dehau]: https://github.com/fdehau
[`cargo-generate`]: https://crates.io/crates/cargo-generate
[License]: ./LICENSE

View File

@@ -8,119 +8,57 @@
default_job = "check"
[jobs.check]
command = ["cargo", "check", "--all-features"]
command = ["cargo", "xtask", "check"]
need_stdout = false
[jobs.check-all]
command = ["cargo", "check", "--all-targets", "--all-features"]
command = ["cargo", "xtask", "check", "--all-features"]
need_stdout = false
[jobs.check-crossterm]
command = [
"cargo",
"check",
"--all-targets",
"--no-default-features",
"--features",
"crossterm",
]
command = ["cargo", "xtask", "check-crossterm"]
need_stdout = false
[jobs.check-termion]
command = [
"cargo",
"check",
"--all-targets",
"--no-default-features",
"--features",
"termion",
]
command = ["cargo", "xtask", "check-termion"]
need_stdout = false
[jobs.check-termwiz]
command = [
"cargo",
"check",
"--all-targets",
"--no-default-features",
"--features",
"termwiz",
]
command = ["cargo", "xtask", "check-termwiz"]
need_stdout = false
[jobs.clippy]
command = ["cargo", "clippy", "--all-targets"]
[jobs.clippy-all]
command = ["cargo", "xtask", "clippy"]
need_stdout = false
[jobs.test]
command = ["cargo", "test", "--all-features"]
command = ["cargo", "xtask", "test"]
need_stdout = true
[jobs.test-unit]
command = ["cargo", "test", "--lib", "--all-features"]
command = ["cargo", "xtask", "test-libs"]
need_stdout = true
[jobs.doc]
command = [
"cargo",
"+nightly",
"doc",
"-Zunstable-options",
"-Zrustdoc-scrape-examples",
"--all-features",
"--no-deps",
]
env.RUSTDOCFLAGS = "--cfg docsrs"
command = ["cargo", "xtask", "docs"]
need_stdout = false
# If the doc compiles, then it opens in your browser and bacon switches
# to the previous job
[jobs.doc-open]
command = [
"cargo",
"+nightly",
"doc",
"-Zunstable-options",
"-Zrustdoc-scrape-examples",
"--all-features",
"--no-deps",
"--open",
]
env.RUSTDOCFLAGS = "--cfg docsrs"
command = ["cargo", "xtask", "docs", "--open"]
on_success = "job:doc"
need_stdout = false
on_success = "job:doc" # so that we don't open the browser at each change
[jobs.coverage]
command = [
"cargo",
"llvm-cov",
"--lcov",
"--output-path",
"target/lcov.info",
"--all-features",
]
command = ["cargo", "xtask", "coverage"]
[jobs.coverage-unit-tests-only]
command = [
"cargo",
"llvm-cov",
"--lcov",
"--output-path",
"target/lcov.info",
"--lib",
"--all-features",
]
command = ["cargo", "xtask", "coverage-unit"]
[jobs.hack]
command = [
"cargo",
"hack",
"test",
"--lib",
"--each-feature",
# "--all-targets",
"--workspace",
]
command = ["cargo", "xtask", "hack"]
[jobs.format]
command = ["cargo", "xtask", "format"]
# You may define here keybindings that would be specific to
# a project, for example a shortcut to launch a specific job.
@@ -135,3 +73,4 @@ v = "job:coverage"
ctrl-v = "job:coverage-unit-tests-only"
u = "job:test-unit"
n = "job:nextest"
f = "job:format"

View File

@@ -1,24 +1 @@
avoid-breaking-exported-api = false
# https://rust-lang.github.io/rust-clippy/master/index.html#/multiple_crate_versions
# ratatui -> bitflags v2.3
# termwiz -> wezterm-blob-leases -> mac_address -> nix -> bitflags v1.3.2
# (also, memoffset, syn, nix, strsim, windows-sys
# crossterm -> all the windows- deps https://github.com/ratatui/ratatui/pull/1064#issuecomment-2078848980
allowed-duplicate-crates = [
"bitflags",
"memoffset",
"nix",
"strsim",
"syn",
"windows-sys",
"windows-targets",
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
"unicode-width",
]

View File

@@ -4,14 +4,16 @@
version = 2
confidence-threshold = 0.8
allow = [
"Apache-2.0",
"BSD-2-Clause",
"BSD-3-Clause",
"ISC",
"MIT",
"Unicode-DFS-2016",
"WTFPL",
"Zlib",
"Apache-2.0",
"BSD-2-Clause",
"BSD-3-Clause",
"ISC",
"MIT",
"OpenSSL",
"Unicode-3.0",
"Unicode-DFS-2016",
"WTFPL",
"Zlib",
]
[advisories]
@@ -24,3 +26,15 @@ multiple-versions = "allow"
unknown-registry = "deny"
unknown-git = "warn"
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
[[licenses.clarify]]
crate = "ring"
# SPDX considers OpenSSL to encompass both the OpenSSL and SSLeay licenses
# https://spdx.org/licenses/OpenSSL.html
# ISC - Both BoringSSL and ring use this for their new files
# MIT - "Files in third_party/ have their own licenses, as described therein. The MIT
# license, for third_party/fiat, which, unlike other third_party directories, is
# compiled into non-test libraries, is included below."
# OpenSSL - Obviously
expression = "ISC AND MIT AND OpenSSL"
license-files = [{ path = "LICENSE", hash = 0xbd0eed23 }]

66
examples/README.md Normal file
View File

@@ -0,0 +1,66 @@
# Examples
This folder contains examples that are more app focused. There are also other examples in example
folders under each crate folder e.g. [ratatui examples], [ratatui-widgets examples].
[ratatui examples]: ../ratatui/examples
[ratatui-widgets examples]: ../ratatui-widgets/examples
You can run these examples using:
```shell
cargo run -p example-name
```
This folder might use unreleased code. Consider viewing the examples in the `latest` branch instead
of the `main` branch for code which is guaranteed to work with the released ratatui version.
> [!WARNING]
>
> There may be backwards incompatible changes in these examples, as they are designed to compile
> against the `main` branch.
>
> There are a few workaround for this problem:
>
> - View the examples as they were when the latest version was release by selecting the tag that
> matches that version. E.g. <https://github.com/ratatui/ratatui/tree/v0.26.1/examples>.
> - If you're viewing this file on GitHub, there is a combo box at the top of this page which
> allows you to select any previous tagged version.
> - To view the code locally, checkout the tag. E.g. `git switch --detach v0.26.1`.
> - Use the latest [alpha version of Ratatui] in your app. These are released weekly on Saturdays.
> - Compile your code against the main branch either locally by adding e.g. `path = "../ratatui"` to
> the dependency, or remotely by adding `git = "https://github.com/ratatui/ratatui"`
>
> For a list of unreleased breaking changes, see [BREAKING-CHANGES.md].
>
> We don't keep the CHANGELOG updated with unreleased changes, check the git commit history or run
> `git-cliff -u` against a cloned version of this repository.
## Demo
This is the original demo example from the main README. It is available for each of the backends.
[Source](./apps/demo/).
![Demo](https://github.com/ratatui/ratatui/blob/images/examples/demo.gif?raw=true)
## Demo2
This is the demo example from the main README and crate page. [Source](./apps/demo2/).
![Demo2](https://github.com/ratatui/ratatui/blob/images/examples/demo2.gif?raw=true)
## Mouse Drawing demo
Shows how to handle mouse events. [Source](./apps/mouse-drawing/).
## Async GitHub demo
Shows how to fetch data from GitHub API asynchronously. [Source](./apps/async-github/).
## Weather demo
Shows how to render weather data using barchart widget. [Source](./apps/weather/).
## Calendar explorer demo
Shows how to render a calendar with different styles. [Source](./apps/calendar-explorer/).

View File

@@ -0,0 +1,22 @@
[package]
name = "async-github"
version = "0.1.0"
authors.workspace = true
documentation.workspace = true
repository.workspace = true
homepage.workspace = true
keywords.workspace = true
categories.workspace = true
readme.workspace = true
license.workspace = true
exclude.workspace = true
edition.workspace = true
rust-version.workspace = true
[dependencies]
color-eyre = "0.6.3"
crossterm = { workspace = true, features = ["event-stream"] }
octocrab = "0.42.1"
ratatui.workspace = true
tokio = { version = "1.43.0", features = ["rt-multi-thread", "macros"] }
tokio-stream = "0.1.17"

View File

@@ -0,0 +1,9 @@
# Async GitHub demo
This example demonstrates how to use Ratatui with widgets that fetch data from GitHub API asynchronously.
To run this demo:
```shell
cargo run -p async-github
```

View File

@@ -1,9 +1,7 @@
//! # [Ratatui] Async example
//!
//! This example demonstrates how to use Ratatui with widgets that fetch data asynchronously. It
//! uses the `octocrab` crate to fetch a list of pull requests from the GitHub API. You will need an
//! environment variable named `GITHUB_TOKEN` with a valid GitHub personal access token. The token
//! does not need any special permissions.
//! uses the `octocrab` crate to fetch a list of pull requests from the GitHub API.
//!
//! <https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token>
//! <https://github.com/settings/tokens/new> to create a new token (select classic, and no scopes)
@@ -34,11 +32,10 @@ use std::{
time::Duration,
};
use color_eyre::{eyre::Context, Result, Section};
use futures::StreamExt;
use color_eyre::Result;
use octocrab::{
params::{pulls::Sort, Direction},
OctocrabBuilder, Page,
Page,
};
use ratatui::{
buffer::Buffer,
@@ -49,29 +46,17 @@ use ratatui::{
widgets::{Block, HighlightSpacing, Row, StatefulWidget, Table, TableState, Widget},
DefaultTerminal, Frame,
};
use tokio_stream::StreamExt;
#[tokio::main]
async fn main() -> Result<()> {
color_eyre::install()?;
init_octocrab()?;
let terminal = ratatui::init();
let app_result = App::default().run(terminal).await;
ratatui::restore();
app_result
}
fn init_octocrab() -> Result<()> {
let token = std::env::var("GITHUB_TOKEN")
.wrap_err("The GITHUB_TOKEN environment variable was not found")
.suggestion(
"Go to https://github.com/settings/tokens/new to create a token, and re-run:
GITHUB_TOKEN=ghp_... cargo run --example async --features crossterm",
)?;
let crab = OctocrabBuilder::new().personal_token(token).build()?;
octocrab::initialise(crab);
Ok(())
}
#[derive(Debug, Default)]
struct App {
should_quit: bool,

View File

@@ -0,0 +1,15 @@
[package]
name = "calendar-explorer"
publish = false
license.workspace = true
edition.workspace = true
rust-version.workspace = true
[dependencies]
color-eyre.workspace = true
crossterm.workspace = true
ratatui.workspace = true
time = { version = "0.3.37", features = ["formatting", "parsing"] }
[lints]
workspace = true

View File

@@ -0,0 +1,9 @@
# Calendar explorer demo
This example shows how to render a calendar with different styles.
To run this demo:
```shell
cargo run -p calendar-explorer
```

View File

@@ -0,0 +1,248 @@
//! A Ratatui example that demonstrates how to render calendar with different styles.
//!
//! Marks the holidays and seasons on the calendar.
//!
//! This example runs with the Ratatui library code in the branch that you are currently reading.
//! See the [`latest`] branch for the code which works with the most recent Ratatui release.
//!
//! [`latest`]: https://github.com/ratatui/ratatui/tree/latest
//! [`BarChart`]: https://docs.rs/ratatui/latest/ratatui/widgets/struct.BarChart.html
use std::fmt;
use color_eyre::Result;
use crossterm::event::{self, Event, KeyCode, KeyEventKind};
use ratatui::{
layout::{Constraint, Layout, Margin, Rect},
style::{Color, Modifier, Style, Stylize},
text::{Line, Text},
widgets::calendar::{CalendarEventStore, Monthly},
DefaultTerminal, Frame,
};
use time::{ext::NumericalDuration, Date, Month, OffsetDateTime};
fn main() -> Result<()> {
color_eyre::install()?;
let terminal = ratatui::init();
let result = run(terminal);
ratatui::restore();
result
}
/// Run the application.
fn run(mut terminal: DefaultTerminal) -> Result<()> {
let mut selected_date = OffsetDateTime::now_local()?.date();
let mut calendar_style = StyledCalendar::Default;
loop {
terminal.draw(|frame| render(frame, calendar_style, selected_date))?;
if let Event::Key(key) = event::read()? {
if key.kind == KeyEventKind::Press {
match key.code {
KeyCode::Char('q') => break Ok(()),
KeyCode::Char('s') => calendar_style = calendar_style.next(),
KeyCode::Char('n') | KeyCode::Tab => selected_date = next_month(selected_date),
KeyCode::Char('p') | KeyCode::BackTab => {
selected_date = previous_month(selected_date);
}
KeyCode::Char('h') | KeyCode::Left => selected_date -= 1.days(),
KeyCode::Char('j') | KeyCode::Down => selected_date += 1.weeks(),
KeyCode::Char('k') | KeyCode::Up => selected_date -= 1.weeks(),
KeyCode::Char('l') | KeyCode::Right => selected_date += 1.days(),
_ => {}
}
}
}
}
}
fn next_month(date: Date) -> Date {
if date.month() == Month::December {
date.replace_month(Month::January)
.unwrap()
.replace_year(date.year() + 1)
.unwrap()
} else {
date.replace_month(date.month().next()).unwrap()
}
}
fn previous_month(date: Date) -> Date {
if date.month() == Month::January {
date.replace_month(Month::December)
.unwrap()
.replace_year(date.year() - 1)
.unwrap()
} else {
date.replace_month(date.month().previous()).unwrap()
}
}
/// Draw the UI with a calendar.
fn render(frame: &mut Frame, calendar_style: StyledCalendar, selected_date: Date) {
let header = Text::from_iter([
Line::from("Calendar Example".bold()),
Line::from(
"<q> Quit | <s> Change Style | <n> Next Month | <p> Previous Month, <hjkl> Move",
),
Line::from(format!(
"Current date: {selected_date} | Current style: {calendar_style}"
)),
]);
let vertical = Layout::vertical([
Constraint::Length(header.height() as u16),
Constraint::Fill(1),
]);
let [text_area, area] = vertical.areas(frame.area());
frame.render_widget(header.centered(), text_area);
calendar_style
.render_year(frame, area, selected_date)
.unwrap();
}
#[derive(Debug, Clone, Copy)]
enum StyledCalendar {
Default,
Surrounding,
WeekdaysHeader,
SurroundingAndWeekdaysHeader,
MonthHeader,
MonthAndWeekdaysHeader,
}
impl StyledCalendar {
// Cycle through the different styles.
const fn next(self) -> Self {
match self {
Self::Default => Self::Surrounding,
Self::Surrounding => Self::WeekdaysHeader,
Self::WeekdaysHeader => Self::SurroundingAndWeekdaysHeader,
Self::SurroundingAndWeekdaysHeader => Self::MonthHeader,
Self::MonthHeader => Self::MonthAndWeekdaysHeader,
Self::MonthAndWeekdaysHeader => Self::Default,
}
}
}
impl fmt::Display for StyledCalendar {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Default => write!(f, "Default"),
Self::Surrounding => write!(f, "Show Surrounding"),
Self::WeekdaysHeader => write!(f, "Show Weekdays Header"),
Self::SurroundingAndWeekdaysHeader => write!(f, "Show Surrounding and Weekdays Header"),
Self::MonthHeader => write!(f, "Show Month Header"),
Self::MonthAndWeekdaysHeader => write!(f, "Show Month Header and Weekdays Header"),
}
}
}
impl StyledCalendar {
fn render_year(self, frame: &mut Frame, area: Rect, date: Date) -> Result<()> {
let events = events(date)?;
let area = area.inner(Margin {
vertical: 1,
horizontal: 1,
});
let rows = Layout::vertical([Constraint::Ratio(1, 3); 3]).split(area);
let areas = rows.iter().flat_map(|row| {
Layout::horizontal([Constraint::Ratio(1, 4); 4])
.split(*row)
.to_vec()
});
for (i, area) in areas.enumerate() {
let month = date
.replace_day(1)
.unwrap()
.replace_month(Month::try_from(i as u8 + 1).unwrap())
.unwrap();
self.render_month(frame, area, month, &events);
}
Ok(())
}
fn render_month(self, frame: &mut Frame, area: Rect, date: Date, events: &CalendarEventStore) {
let calendar = match self {
Self::Default => Monthly::new(date, events)
.default_style(Style::new().bold().bg(Color::Rgb(50, 50, 50)))
.show_month_header(Style::default()),
Self::Surrounding => Monthly::new(date, events)
.default_style(Style::new().bold().bg(Color::Rgb(50, 50, 50)))
.show_month_header(Style::default())
.show_surrounding(Style::new().dim()),
Self::WeekdaysHeader => Monthly::new(date, events)
.default_style(Style::new().bold().bg(Color::Rgb(50, 50, 50)))
.show_month_header(Style::default())
.show_weekdays_header(Style::new().bold().green()),
Self::SurroundingAndWeekdaysHeader => Monthly::new(date, events)
.default_style(Style::new().bold().bg(Color::Rgb(50, 50, 50)))
.show_month_header(Style::default())
.show_surrounding(Style::new().dim())
.show_weekdays_header(Style::new().bold().green()),
Self::MonthHeader => Monthly::new(date, events)
.default_style(Style::new().bold().bg(Color::Rgb(50, 50, 50)))
.show_month_header(Style::default())
.show_month_header(Style::new().bold().green()),
Self::MonthAndWeekdaysHeader => Monthly::new(date, events)
.default_style(Style::new().bold().bg(Color::Rgb(50, 50, 50)))
.show_month_header(Style::default())
.show_weekdays_header(Style::new().bold().dim().light_yellow()),
};
frame.render_widget(calendar, area);
}
}
/// Makes a list of dates for the current year.
fn events(selected_date: Date) -> Result<CalendarEventStore> {
const SELECTED: Style = Style::new()
.fg(Color::White)
.bg(Color::Red)
.add_modifier(Modifier::BOLD);
const HOLIDAY: Style = Style::new()
.fg(Color::Red)
.add_modifier(Modifier::UNDERLINED);
const SEASON: Style = Style::new()
.fg(Color::Green)
.bg(Color::Black)
.add_modifier(Modifier::UNDERLINED);
let mut list = CalendarEventStore::today(
Style::default()
.add_modifier(Modifier::BOLD)
.bg(Color::Blue),
);
let y = selected_date.year();
// new year's
list.add(Date::from_calendar_date(y, Month::January, 1)?, HOLIDAY);
// next new_year's for December "show surrounding"
list.add(Date::from_calendar_date(y + 1, Month::January, 1)?, HOLIDAY);
// groundhog day
list.add(Date::from_calendar_date(y, Month::February, 2)?, HOLIDAY);
// april fool's
list.add(Date::from_calendar_date(y, Month::April, 1)?, HOLIDAY);
// earth day
list.add(Date::from_calendar_date(y, Month::April, 22)?, HOLIDAY);
// star wars day
list.add(Date::from_calendar_date(y, Month::May, 4)?, HOLIDAY);
// festivus
list.add(Date::from_calendar_date(y, Month::December, 23)?, HOLIDAY);
// new year's eve
list.add(Date::from_calendar_date(y, Month::December, 31)?, HOLIDAY);
// seasons
// spring equinox
list.add(Date::from_calendar_date(y, Month::March, 22)?, SEASON);
// summer solstice
list.add(Date::from_calendar_date(y, Month::June, 21)?, SEASON);
// fall equinox
list.add(Date::from_calendar_date(y, Month::September, 22)?, SEASON);
// winter solstice
list.add(Date::from_calendar_date(y, Month::December, 21)?, SEASON);
// selected date
list.add(selected_date, SELECTED);
Ok(list)
}

View File

@@ -0,0 +1,15 @@
[package]
name = "canvas"
publish = false
license.workspace = true
edition.workspace = true
rust-version.workspace = true
[dependencies]
color-eyre.workspace = true
crossterm.workspace = true
itertools.workspace = true
ratatui.workspace = true
[lints]
workspace = true

View File

@@ -0,0 +1,9 @@
# Canvas demo
This example shows how to render various shapes and a map on a canvas.
To run this demo:
```shell
cargo run -p canvas
```

View File

@@ -1,18 +1,13 @@
//! # [Ratatui] Canvas example
//!
//! The latest version of this example is available in the [examples] folder in the repository.
//!
//! Please note that the examples are designed to be run against the `main` branch of the Github
//! repository. This means that you may not be able to compile with the latest release version on
//! crates.io, or the one that you have installed locally.
//!
//! See the [examples readme] for more information on finding examples that match the version of the
//! library you are using.
//!
//! [Ratatui]: https://github.com/ratatui/ratatui
//! [examples]: https://github.com/ratatui/ratatui/blob/main/examples
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
/// A Ratatui example that demonstrates how to draw on a canvas.
///
/// This example demonstrates how to draw various shapes such as rectangles, circles, and lines
/// on a canvas. It also demonstrates how to draw a map.
///
/// This example runs with the Ratatui library code in the branch that you are currently
/// reading. See the [`latest`] branch for the code which works with the most recent Ratatui
/// release.
///
/// [`latest`]: https://github.com/ratatui/ratatui/tree/latest
use std::{
io::stdout,
time::{Duration, Instant},
@@ -29,6 +24,7 @@ use ratatui::{
layout::{Constraint, Layout, Position, Rect},
style::{Color, Stylize},
symbols::Marker,
text::Text,
widgets::{
canvas::{Canvas, Circle, Map, MapResolution, Points, Rectangle},
Block, Widget,
@@ -54,7 +50,6 @@ struct App {
playground: Rect,
vx: f64,
vy: f64,
tick_count: u64,
marker: Marker,
points: Vec<Position>,
is_drawing: bool,
@@ -75,7 +70,6 @@ impl App {
playground: Rect::new(10, 10, 200, 100),
vx: 1.0,
vy: 1.0,
tick_count: 0,
marker: Marker::Dot,
points: vec![],
is_drawing: false,
@@ -114,6 +108,15 @@ impl App {
KeyCode::Up | KeyCode::Char('k') => self.y -= 1.0,
KeyCode::Right | KeyCode::Char('l') => self.x += 1.0,
KeyCode::Left | KeyCode::Char('h') => self.x -= 1.0,
KeyCode::Enter => {
self.marker = match self.marker {
Marker::Dot => Marker::Braille,
Marker::Braille => Marker::Block,
Marker::Block => Marker::HalfBlock,
Marker::HalfBlock => Marker::Bar,
Marker::Bar => Marker::Dot,
};
}
_ => {}
}
}
@@ -130,17 +133,6 @@ impl App {
}
fn on_tick(&mut self) {
self.tick_count += 1;
// only change marker every 180 ticks (3s) to avoid stroboscopic effect
if (self.tick_count % 180) == 0 {
self.marker = match self.marker {
Marker::Dot => Marker::Braille,
Marker::Braille => Marker::Block,
Marker::Block => Marker::HalfBlock,
Marker::HalfBlock => Marker::Bar,
Marker::Bar => Marker::Dot,
};
}
// bounce the ball by flipping the velocity vector
let ball = &self.ball;
let playground = self.playground;
@@ -154,18 +146,28 @@ impl App {
{
self.vy = -self.vy;
}
self.ball.x += self.vx;
self.ball.y += self.vy;
}
fn draw(&self, frame: &mut Frame) {
let header = Text::from_iter([
"Canvas Example".bold(),
"<q> Quit | <enter> Change Marker | <hjkl> Move".into(),
]);
let vertical = Layout::vertical([
Constraint::Length(header.height() as u16),
Constraint::Percentage(50),
Constraint::Percentage(50),
]);
let [text_area, up, down] = vertical.areas(frame.area());
frame.render_widget(header.centered(), text_area);
let horizontal =
Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]);
let vertical = Layout::vertical([Constraint::Percentage(50), Constraint::Percentage(50)]);
let [left, right] = horizontal.areas(frame.area());
let [draw, map] = vertical.areas(left);
let [pong, boxes] = vertical.areas(right);
let [draw, pong] = horizontal.areas(up);
let [map, boxes] = horizontal.areas(down);
frame.render_widget(self.map_canvas(), map);
frame.render_widget(self.draw_canvas(draw), draw);

View File

@@ -0,0 +1,14 @@
[package]
name = "chart"
publish = false
license.workspace = true
edition.workspace = true
rust-version.workspace = true
[dependencies]
color-eyre.workspace = true
crossterm.workspace = true
ratatui.workspace = true
[lints]
workspace = true

View File

@@ -0,0 +1,9 @@
# Chart demo
This example shows how to render line, bar, and scatter charts.
To run this demo:
```shell
cargo run -p chart
```

View File

@@ -1,18 +1,13 @@
//! # [Ratatui] Chart example
//!
//! The latest version of this example is available in the [examples] folder in the repository.
//!
//! Please note that the examples are designed to be run against the `main` branch of the Github
//! repository. This means that you may not be able to compile with the latest release version on
//! crates.io, or the one that you have installed locally.
//!
//! See the [examples readme] for more information on finding examples that match the version of the
//! library you are using.
//!
//! [Ratatui]: https://github.com/ratatui/ratatui
//! [examples]: https://github.com/ratatui/ratatui/blob/main/examples
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
/// A Ratatui example that demonstrates how to handle charts.
///
/// This example demonstrates how to draw various types of charts such as line, bar, and
/// scatter charts.
///
/// This example runs with the Ratatui library code in the branch that you are currently
/// reading. See the [`latest`] branch for the code which works with the most recent Ratatui
/// release.
///
/// [`latest`]: https://github.com/ratatui/ratatui/tree/latest
use std::time::{Duration, Instant};
use color_eyre::Result;

View File

@@ -0,0 +1,15 @@
[package]
name = "color-explorer"
publish = false
license.workspace = true
edition.workspace = true
rust-version.workspace = true
[dependencies]
color-eyre.workspace = true
crossterm.workspace = true
itertools.workspace = true
ratatui.workspace = true
[lints]
workspace = true

View File

@@ -0,0 +1,9 @@
# Color explorer demo
This example shows how to handle the supported colors.
To run this demo:
```shell
cargo run -p color-explorer
```

View File

@@ -1,20 +1,12 @@
//! # [Ratatui] Colors example
//! A Ratatui example that demonstrates how to handle colors.
//!
//! The latest version of this example is available in the [examples] folder in the repository.
//! This example shows all the colors supported by Ratatui. It will render a grid of foreground
//! and background colors with their names and indexes.
//!
//! Please note that the examples are designed to be run against the `main` branch of the Github
//! repository. This means that you may not be able to compile with the latest release version on
//! crates.io, or the one that you have installed locally.
//! This example runs with the Ratatui library code in the branch that you are currently reading.
//! See the [`latest`] branch for the code which works with the most recent Ratatui release.
//!
//! See the [examples readme] for more information on finding examples that match the version of the
//! library you are using.
//!
//! [Ratatui]: https://github.com/ratatui/ratatui
//! [examples]: https://github.com/ratatui/ratatui/blob/main/examples
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
// This example shows all the colors supported by ratatui. It will render a grid of foreground
// and background colors with their names and indexes.
//! [`latest`]: https://github.com/ratatui/ratatui/tree/latest
use color_eyre::Result;
use itertools::Itertools;

View File

@@ -0,0 +1,17 @@
[package]
name = "demo"
publish = false
license.workspace = true
edition.workspace = true
rust-version.workspace = true
[features]
default = ["crossterm"]
crossterm = ["ratatui/crossterm"]
termion = ["ratatui/termion"]
termwiz = ["ratatui/termwiz"]
[dependencies]
clap = { version = "4.5.23", features = ["derive"] }
rand = "0.8.5"
ratatui.workspace = true

View File

@@ -0,0 +1,25 @@
# Demo example
This is the original demo that was developed for Tui-rs (the library that Ratatui was forked from).
![demo.gif](https://github.com/ratatui/ratatui/blob/images/examples/demo.gif?raw=true)
This example is available for each backend. To run it:
## crossterm
```shell
cargo run -p demo
```
## termion
```shell
cargo run -p demo --no-default-features --features termion
```
## termwiz
```shell
cargo run -p demo --no-default-features --features termwiz
```

View File

@@ -15,7 +15,7 @@
use std::{error::Error, time::Duration};
use argh::FromArgs;
use clap::Parser;
mod app;
#[cfg(feature = "crossterm")]
@@ -28,28 +28,29 @@ mod termwiz;
mod ui;
/// Demo
#[derive(Debug, FromArgs)]
#[derive(Debug, Parser)]
struct Cli {
/// time in ms between two ticks.
#[argh(option, default = "250")]
#[arg(short, long, default_value_t = 250)]
tick_rate: u64,
/// whether unicode symbols are used to improve the overall look of the app
#[argh(option, default = "true")]
enhanced_graphics: bool,
#[arg(short, long, default_value_t = true)]
unicode: bool,
}
fn main() -> Result<(), Box<dyn Error>> {
let cli: Cli = argh::from_env();
let cli = Cli::parse();
let tick_rate = Duration::from_millis(cli.tick_rate);
#[cfg(feature = "crossterm")]
crate::crossterm::run(tick_rate, cli.enhanced_graphics)?;
crate::crossterm::run(tick_rate, cli.unicode)?;
#[cfg(all(not(windows), feature = "termion", not(feature = "crossterm")))]
crate::termion::run(tick_rate, cli.enhanced_graphics)?;
crate::termion::run(tick_rate, cli.unicode)?;
#[cfg(all(
feature = "termwiz",
not(feature = "crossterm"),
not(feature = "termion")
))]
crate::termwiz::run(tick_rate, cli.enhanced_graphics)?;
crate::termwiz::run(tick_rate, cli.unicode)?;
Ok(())
}

View File

@@ -0,0 +1,19 @@
[package]
name = "demo2"
publish = false
license.workspace = true
edition.workspace = true
rust-version.workspace = true
[dependencies]
color-eyre = "0.6.3"
crossterm.workspace = true
indoc.workspace = true
itertools.workspace = true
palette = "0.7.6"
rand = "0.8.5"
rand_chacha = "0.3.1"
ratatui = { workspace = true, features = ["all-widgets"] }
strum.workspace = true
time = "0.3.37"
unicode-width = "0.2.0"

View File

@@ -0,0 +1,9 @@
## Demo2
This is the demo example from the main README and crate page. Source: [demo2](./demo2/).
```shell
cargo run -p demo2
```
![Demo2](https://github.com/ratatui/ratatui/blob/images/examples/demo2.gif?raw=true)

View File

@@ -0,0 +1,75 @@
use ratatui::{
buffer::Buffer,
layout::{Alignment, Constraint, Layout, Margin, Rect},
widgets::{
Block, Borders, Clear, MascotEyeColor, Padding, Paragraph, RatatuiMascot, Widget, Wrap,
},
};
use crate::{RgbSwatch, THEME};
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct AboutTab {
row_index: usize,
}
impl AboutTab {
pub fn prev_row(&mut self) {
self.row_index = self.row_index.saturating_sub(1);
}
pub fn next_row(&mut self) {
self.row_index = self.row_index.saturating_add(1);
}
}
impl Widget for AboutTab {
fn render(self, area: Rect, buf: &mut Buffer) {
RgbSwatch.render(area, buf);
let horizontal = Layout::horizontal([Constraint::Length(34), Constraint::Min(0)]);
let [logo_area, description] = horizontal.areas(area);
render_crate_description(description, buf);
let eye_state = if self.row_index % 2 == 0 {
MascotEyeColor::Default
} else {
MascotEyeColor::Red
};
RatatuiMascot::default().set_eye(eye_state).render(
logo_area.inner(Margin {
vertical: 0,
horizontal: 2,
}),
buf,
);
}
}
fn render_crate_description(area: Rect, buf: &mut Buffer) {
let area = area.inner(Margin {
vertical: 4,
horizontal: 2,
});
Clear.render(area, buf); // clear out the color swatches
Block::new().style(THEME.content).render(area, buf);
let area = area.inner(Margin {
vertical: 1,
horizontal: 2,
});
let text = "- cooking up terminal user interfaces -
Ratatui is a Rust crate that provides widgets (e.g. Paragraph, Table) and draws them to the \
screen efficiently every frame.";
Paragraph::new(text)
.style(THEME.description)
.block(
Block::new()
.title(" Ratatui ")
.title_alignment(Alignment::Center)
.borders(Borders::TOP)
.border_style(THEME.description_title)
.padding(Padding::new(0, 0, 0, 0)),
)
.wrap(Wrap { trim: true })
.scroll((0, 0))
.render(area, buf);
}

View File

@@ -25,7 +25,7 @@ impl Ingredient {
}
}
impl<'a> From<Ingredient> for Row<'a> {
impl From<Ingredient> for Row<'_> {
fn from(i: Ingredient) -> Self {
Row::new(vec![i.quantity, i.name]).height(i.height())
}

View File

@@ -22,10 +22,8 @@ pub struct KeyBinding {
}
pub struct Logo {
pub rat: Color,
pub rat_eye: Color,
pub rat_eye_alt: Color,
pub term: Color,
}
pub struct Email {
@@ -77,10 +75,8 @@ pub const THEME: Theme = Theme {
description: Style::new().fg(LIGHT_GRAY).bg(DARK_BLUE),
description_title: Style::new().fg(LIGHT_GRAY).add_modifier(Modifier::BOLD),
logo: Logo {
rat: WHITE,
rat_eye: BLACK,
rat_eye_alt: RED,
term: BLACK,
},
key_binding: KeyBinding {
key: Style::new().fg(BLACK).bg(DARK_GRAY),

View File

@@ -0,0 +1,16 @@
[package]
name = "input-form"
publish = false
license.workspace = true
edition.workspace = true
rust-version.workspace = true
[dependencies]
color-eyre.workspace = true
crossterm.workspace = true
ratatui.workspace = true
serde.workspace = true
serde_json.workspace = true
[lints]
workspace = true

View File

@@ -0,0 +1,27 @@
# Input Form example
This example demonstrates how to handle input across several form fields (2 strings and an number).
It uses an enum to track the focused field, and sends keyboard events to one which is current.
Run this example with:
```shell
cargo run -p input-form
```
This example does not handle things like cursor movement within the line (just keys and backspace).
Most apps would benefit from using the following crates for text input rather than directly using
strings:
- [`tui-input`](https://crates.io/crates/tui-input)
- [`tui-prompts`](https://crates.io/crates/tui-prompts)
- [`tui-textarea`](https://crates.io/crates/tui-textarea)
- [`rat-salsa`](https://crates.io/crates/rat-salsa)
Some more ideas for handling focus can be found in:
- [`focusable`](https://crates.io/crates/focusable) (see also [Ratatui forum
post](https://forum.ratatui.rs/t/focusable-crate-manage-focus-state-for-your-widgets/73))
- [`rat-focus`](https://crates.io/crates/rat-focus)
- A useful [`Bevy` discssion](https://github.com/bevyengine/bevy/discussions/15374) about focus
more generally.

View File

@@ -0,0 +1,270 @@
//! A Ratatui example that demonstrates how to handle input form focus
//!
//! This example demonstrates how to handle cursor and input focus between multiple fields in a
//! form. You can navigate between fields using the Tab key.
//!
//! This does not handle cursor movement etc. This is just a simple example. In a real application,
//! consider using [`tui-input`], or [`tui-prompts`], or [`tui-textarea`].
//!
//! This example runs with the Ratatui library code in the branch that you are currently reading.
//! See the [`latest`] branch for the code which works with the most recent Ratatui release.
//!
//! [`latest`]: https://github.com/ratatui/ratatui/tree/latest
//! [`tui-input`]: https://crates.io/crates/tui-input
//! [`tui-prompts`]: https://crates.io/crates/tui-prompts
//! [`tui-textarea`]: https://crates.io/crates/tui-textarea
use color_eyre::Result;
use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind};
use ratatui::{
buffer::Buffer,
layout::{Constraint, Layout, Offset, Rect},
style::Stylize,
text::Line,
widgets::Widget,
DefaultTerminal, Frame,
};
use serde::Serialize;
fn main() -> Result<()> {
color_eyre::install()?;
let terminal = ratatui::init();
let result = App::default().run(terminal);
ratatui::restore();
// serialize the form to JSON if the user submitted it, otherwise print "Canceled"
match result {
Ok(Some(form)) => println!("{}", serde_json::to_string_pretty(&form)?),
Ok(None) => println!("Canceled"),
Err(err) => eprintln!("{err}"),
}
Ok(())
}
#[derive(Default)]
struct App {
state: AppState,
form: InputForm,
}
#[derive(Default, PartialEq, Eq)]
enum AppState {
#[default]
Running,
Cancelled,
Submitted,
}
impl App {
fn run(mut self, mut terminal: DefaultTerminal) -> Result<Option<InputForm>> {
while self.state == AppState::Running {
terminal.draw(|frame| self.render(frame))?;
self.handle_events()?;
}
match self.state {
AppState::Cancelled => Ok(None),
AppState::Submitted => Ok(Some(self.form)),
AppState::Running => unreachable!(),
}
}
fn render(&self, frame: &mut Frame) {
self.form.render(frame);
}
fn handle_events(&mut self) -> Result<()> {
match event::read()? {
Event::Key(event) if event.kind == KeyEventKind::Press => match event.code {
KeyCode::Esc => self.state = AppState::Cancelled,
KeyCode::Enter => self.state = AppState::Submitted,
_ => self.form.on_key_press(event),
},
_ => {}
}
Ok(())
}
}
#[derive(Serialize)]
struct InputForm {
#[serde(skip)]
focus: Focus,
first_name: StringField,
last_name: StringField,
age: AgeField,
}
impl Default for InputForm {
fn default() -> Self {
Self {
focus: Focus::FirstName,
first_name: StringField::new("First Name"),
last_name: StringField::new("Last Name"),
age: AgeField::new("Age"),
}
}
}
impl InputForm {
// Handle focus navigation or pass the event to the focused field.
fn on_key_press(&mut self, event: KeyEvent) {
match event.code {
KeyCode::Tab => self.focus = self.focus.next(),
_ => match self.focus {
Focus::FirstName => self.first_name.on_key_press(event),
Focus::LastName => self.last_name.on_key_press(event),
Focus::Age => self.age.on_key_press(event),
},
}
}
/// Render the form with the current focus.
///
/// The cursor is placed at the end of the focused field.
fn render(&self, frame: &mut Frame) {
let [first_name_area, last_name_area, age_area] =
Layout::vertical(Constraint::from_lengths([1, 1, 1])).areas(frame.area());
frame.render_widget(&self.first_name, first_name_area);
frame.render_widget(&self.last_name, last_name_area);
frame.render_widget(&self.age, age_area);
let cursor_position = match self.focus {
Focus::FirstName => first_name_area.offset(self.first_name.cursor_offset()),
Focus::LastName => last_name_area.offset(self.last_name.cursor_offset()),
Focus::Age => age_area.offset(self.age.cursor_offset()),
};
frame.set_cursor_position(cursor_position);
}
}
#[derive(Default, PartialEq, Eq)]
enum Focus {
#[default]
FirstName,
LastName,
Age,
}
impl Focus {
// Round-robin focus order.
const fn next(&self) -> Self {
match self {
Self::FirstName => Self::LastName,
Self::LastName => Self::Age,
Self::Age => Self::FirstName,
}
}
}
/// A new-type representing a string field with a label.
#[derive(Debug, Serialize)]
struct StringField {
#[serde(skip)]
label: &'static str,
value: String,
}
impl StringField {
const fn new(label: &'static str) -> Self {
Self {
label,
value: String::new(),
}
}
/// Handle input events for the string input.
fn on_key_press(&mut self, event: KeyEvent) {
match event.code {
KeyCode::Char(c) => self.value.push(c),
KeyCode::Backspace => {
self.value.pop();
}
_ => {}
}
}
fn cursor_offset(&self) -> Offset {
let x = (self.label.len() + self.value.len() + 2) as i32;
Offset::new(x, 0)
}
}
impl Widget for &StringField {
fn render(self, area: Rect, buf: &mut Buffer) {
let constraints = [
Constraint::Length(self.label.len() as u16 + 2),
Constraint::Fill(1),
];
let [label_area, value_area] = Layout::horizontal(constraints).areas(area);
let label = Line::from_iter([self.label, ": "]).bold();
label.render(label_area, buf);
self.value.clone().render(value_area, buf);
}
}
/// A new-type representing a person's age in years (0-130).
#[derive(Default, Clone, Copy, Serialize)]
struct AgeField {
#[serde(skip)]
label: &'static str,
value: u8,
}
impl AgeField {
const MAX: u8 = 130;
const fn new(label: &'static str) -> Self {
Self { label, value: 0 }
}
/// Handle input events for the age input.
///
/// Digits are accepted as input, with any input which would exceed the maximum age being
/// ignored. The up/down arrow keys and 'j'/'k' keys can be used to increment/decrement the
/// age.
fn on_key_press(&mut self, event: KeyEvent) {
match event.code {
KeyCode::Char(digit @ '0'..='9') => {
let value = self
.value
.saturating_mul(10)
.saturating_add(digit as u8 - b'0');
if value <= Self::MAX {
self.value = value;
}
}
KeyCode::Backspace => self.value /= 10,
KeyCode::Up | KeyCode::Char('k') => self.increment(),
KeyCode::Down | KeyCode::Char('j') => self.decrement(),
_ => {}
};
}
fn increment(&mut self) {
self.value = self.value.saturating_add(1).min(Self::MAX);
}
fn decrement(&mut self) {
self.value = self.value.saturating_sub(1);
}
fn cursor_offset(&self) -> Offset {
let x = (self.label.len() + self.value.to_string().len() + 2) as i32;
Offset::new(x, 0)
}
}
impl Widget for &AgeField {
fn render(self, area: Rect, buf: &mut Buffer) {
let constraints = [
Constraint::Length(self.label.len() as u16 + 2),
Constraint::Fill(1),
];
let [label_area, value_area] = Layout::horizontal(constraints).areas(area);
let label = Line::from_iter([self.label, ": "]).bold();
let value = self.value.to_string();
label.render(label_area, buf);
value.render(value_area, buf);
}
}

View File

@@ -0,0 +1,17 @@
[package]
name = "mouse-drawing"
publish = false
license.workspace = true
edition.workspace = true
rust-version.workspace = true
[dependencies]
color-eyre.workspace = true
crossterm.workspace = true
## a collection of line drawing algorithms (e.g. Bresenham's line algorithm)
line_drawing = "1.0.0"
rand = "0.8.5"
ratatui.workspace = true
[lints]
workspace = true

View File

@@ -0,0 +1,9 @@
# Mouse drawing demo
This example shows how to receive mouse and handle mouse events.
To run this demo:
```shell
cargo run -p mouse-drawing
```

View File

@@ -0,0 +1,123 @@
/// A Ratatui example that demonstrates how to handle mouse events.
///
/// This example demonstrates how to handle mouse events in Ratatui. You can draw lines by
/// clicking and dragging the mouse.
///
/// This example runs with the Ratatui library code in the branch that you are currently
/// reading. See the [`latest`] branch for the code which works with the most recent Ratatui
/// release.
///
/// [`latest`]: https://github.com/ratatui/ratatui/tree/latest
use color_eyre::Result;
use crossterm::{
event::{
self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEvent, MouseEvent,
MouseEventKind,
},
execute,
};
use ratatui::{
layout::{Position, Rect, Size},
style::{Color, Stylize},
symbols,
text::Line,
DefaultTerminal, Frame,
};
fn main() -> Result<()> {
color_eyre::install()?;
let terminal = ratatui::init();
let result = MouseDrawingApp::default().run(terminal);
ratatui::restore();
result
}
#[derive(Default)]
struct MouseDrawingApp {
// Whether the app should exit
pub should_exit: bool,
// The last known mouse position
pub mouse_position: Option<Position>,
// The points that have been clicked / drawn by dragging the mouse
pub points: Vec<(Position, Color)>,
// The color to draw with
pub current_color: Color,
}
impl MouseDrawingApp {
fn run(mut self, mut terminal: DefaultTerminal) -> Result<()> {
execute!(std::io::stdout(), EnableMouseCapture)?;
while !self.should_exit {
terminal.draw(|frame| self.render(frame))?;
self.handle_events()?;
}
execute!(std::io::stdout(), DisableMouseCapture)?;
Ok(())
}
fn handle_events(&mut self) -> Result<()> {
match event::read()? {
Event::Key(event) => self.on_key_event(event),
Event::Mouse(event) => self.on_mouse_event(event),
_ => {}
}
Ok(())
}
/// Quit the app if the user presses 'q' or 'Esc'
fn on_key_event(&mut self, event: KeyEvent) {
match event.code {
KeyCode::Char(' ') => {
self.current_color = Color::Rgb(rand::random(), rand::random(), rand::random());
}
KeyCode::Char('q') | KeyCode::Esc => self.should_exit = true,
_ => {}
}
}
/// Adds any points which were clicked or dragged to the `points` vector.
fn on_mouse_event(&mut self, event: MouseEvent) {
let position = Position::new(event.column, event.row);
match event.kind {
MouseEventKind::Down(_) => self.points.push((position, self.current_color)),
MouseEventKind::Drag(_) => self.draw_line(position),
_ => {}
}
self.mouse_position = Some(position);
}
/// Draw a line between the last point and the given position
fn draw_line(&mut self, position: Position) {
if let Some(start) = self.points.last() {
let (x0, y0) = (i32::from(start.0.x), i32::from(start.0.y));
let (x1, y1) = (i32::from(position.x), i32::from(position.y));
for (x, y) in line_drawing::Bresenham::new((x0, y0), (x1, y1)) {
let point = (Position::new(x as u16, y as u16), self.current_color);
self.points.push(point);
}
}
}
fn render(&self, frame: &mut Frame) {
// call order is important here as later elements are drawn on top of earlier elements
self.render_points(frame);
self.render_mouse_cursor(frame);
let value = "Mouse Example ('Esc' to quit. Click / drag to draw. 'Space' to change color)";
let title = Line::from(value).centered();
frame.render_widget(title, frame.area());
}
fn render_points(&self, frame: &mut Frame<'_>) {
for (position, color) in &self.points {
let area = Rect::from((*position, Size::new(1, 1))).clamp(frame.area());
frame.render_widget(symbols::block::FULL.fg(*color), area);
}
}
fn render_mouse_cursor(&self, frame: &mut Frame<'_>) {
if let Some(position) = self.mouse_position {
let area = Rect::from((position, Size::new(1, 1))).clamp(frame.area());
frame.render_widget("".bg(self.current_color), area);
}
}
}

View File

@@ -0,0 +1,15 @@
[package]
name = "weather"
publish = false
license.workspace = true
edition.workspace = true
rust-version.workspace = true
[dependencies]
color-eyre.workspace = true
crossterm.workspace = true
rand = "0.8.5"
ratatui.workspace = true
[lints]
workspace = true

View File

@@ -0,0 +1,9 @@
# Weather demo
This example shows how to render weather data using barchart widget.
To run this demo:
```shell
cargo run -p weather
```

View File

@@ -1,26 +1,21 @@
//! # [Ratatui] `BarChart` example
//! A Ratatui example that demonstrates how to render weather data using [`BarChart`] widget.
//!
//! The latest version of this example is available in the [examples] folder in the repository.
//! Generates random temperature data for each hour of the day and renders it as a vertical bar.
//!
//! Please note that the examples are designed to be run against the `main` branch of the Github
//! repository. This means that you may not be able to compile with the latest release version on
//! crates.io, or the one that you have installed locally.
//! This example runs with the Ratatui library code in the branch that you are currently reading.
//! See the [`latest`] branch for the code which works with the most recent Ratatui release.
//!
//! See the [examples readme] for more information on finding examples that match the version of the
//! library you are using.
//!
//! [Ratatui]: https://github.com/ratatui/ratatui
//! [examples]: https://github.com/ratatui/ratatui/blob/main/examples
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
//! [`latest`]: https://github.com/ratatui/ratatui/tree/latest
//! [`BarChart`]: https://docs.rs/ratatui/latest/ratatui/widgets/struct.BarChart.html
use color_eyre::Result;
use rand::{thread_rng, Rng};
use ratatui::{
crossterm::event::{self, Event, KeyCode, KeyEventKind},
layout::{Constraint, Direction, Layout},
layout::{Constraint, Layout},
style::{Color, Style, Stylize},
text::Line,
widgets::{Bar, BarChart, BarGroup, Block},
widgets::{Bar, BarChart, BarGroup},
DefaultTerminal, Frame,
};
@@ -65,17 +60,12 @@ impl App {
}
fn draw(&self, frame: &mut Frame) {
let [title, vertical, horizontal] = Layout::vertical([
Constraint::Length(1),
Constraint::Fill(1),
Constraint::Fill(1),
])
.spacing(1)
.areas(frame.area());
let [title, main] = Layout::vertical([Constraint::Length(1), Constraint::Fill(1)])
.spacing(1)
.areas(frame.area());
frame.render_widget("Barchart".bold().into_centered_line(), title);
frame.render_widget(vertical_barchart(&self.temperatures), vertical);
frame.render_widget(horizontal_barchart(&self.temperatures), horizontal);
frame.render_widget("Weather demo".bold().into_centered_line(), title);
frame.render_widget(vertical_barchart(&self.temperatures), main);
}
}
@@ -86,10 +76,8 @@ fn vertical_barchart(temperatures: &[u8]) -> BarChart {
.enumerate()
.map(|(hour, value)| vertical_bar(hour, value))
.collect();
let title = Line::from("Weather (Vertical)").centered();
BarChart::default()
.data(BarGroup::default().bars(&bars))
.block(Block::new().title(title))
.bar_width(5)
}
@@ -102,32 +90,6 @@ fn vertical_bar(hour: usize, temperature: &u8) -> Bar {
.value_style(temperature_style(*temperature).reversed())
}
/// Create a horizontal bar chart from the temperatures data.
fn horizontal_barchart(temperatures: &[u8]) -> BarChart {
let bars: Vec<Bar> = temperatures
.iter()
.enumerate()
.map(|(hour, value)| horizontal_bar(hour, value))
.collect();
let title = Line::from("Weather (Horizontal)").centered();
BarChart::default()
.block(Block::new().title(title))
.data(BarGroup::default().bars(&bars))
.bar_width(1)
.bar_gap(0)
.direction(Direction::Horizontal)
}
fn horizontal_bar(hour: usize, temperature: &u8) -> Bar {
let style = temperature_style(*temperature);
Bar::default()
.value(u64::from(*temperature))
.label(Line::from(format!("{hour:>02}:00")))
.text_value(format!("{temperature:>3}°"))
.style(style)
.value_style(style.reversed())
}
/// create a yellow to red value based on the value (50-90)
fn temperature_style(value: u8) -> Style {
let green = (255.0 * (1.0 - f64::from(value - 50) / 40.0)) as u8;

View File

@@ -4,7 +4,7 @@ description = """
Core types and traits for the Ratatui Terminal UI library.
Widget libraries should use this crate. Applications should use the main Ratatui crate.
"""
version = "0.1.0-alpha.0"
version = "0.1.0-alpha.2"
readme = "README.md"
authors.workspace = true
documentation.workspace = true
@@ -24,6 +24,9 @@ rustdoc-args = ["--cfg", "docsrs"]
[features]
default = []
## enables conversions to / from colors, modifiers, and styles in the ['anstyle'] crate
anstyle = ["dep:anstyle"]
## enables conversions from colors in the [`palette`] crate to [`Color`](crate::style::Color).
palette = ["dep:palette"]
@@ -40,6 +43,7 @@ scrolling-regions = []
serde = ["dep:serde", "bitflags/serde", "compact_str/serde"]
[dependencies]
anstyle = { version = "1", optional = true }
bitflags = "2.3"
cassowary = "0.3"
compact_str = "0.8.0"
@@ -51,20 +55,15 @@ palette = { version = "0.7.6", optional = true }
paste = "1.0.2"
serde = { workspace = true, optional = true }
strum.workspace = true
thiserror = "2"
unicode-segmentation.workspace = true
unicode-truncate = "2"
unicode-width.workspace = true
[dev-dependencies]
pretty_assertions.workspace = true
ratatui = { workspace = true, features = ["crossterm", "termwiz"] }
rstest.workspace = true
serde_json.workspace = true
[target.'cfg(not(windows))'.dev-dependencies]
ratatui = { workspace = true, features = ["termion"] }
[lints.clippy]
# we often split up a module into multiple files with the main type in a file named after the
# module, so we want to allow this pattern
module_inception = "allow"
[lints]
workspace = true

View File

@@ -24,7 +24,7 @@
//!
//! # Example
//!
//! ```rust,no_run
//! ```rust,ignore
//! use std::io::stdout;
//!
//! use ratatui::{backend::CrosstermBackend, Terminal};
@@ -171,7 +171,7 @@ pub trait Backend {
/// See also [`show_cursor`].
/// # Example
///
/// ```rust
/// ```rust,ignore
/// # use ratatui::backend::{TestBackend};
/// # let mut backend = TestBackend::new(80, 25);
/// use ratatui::backend::Backend;
@@ -208,7 +208,7 @@ pub trait Backend {
///
/// # Example
///
/// ```rust
/// ```rust,ignore
/// # use ratatui::backend::{TestBackend};
/// # let mut backend = TestBackend::new(80, 25);
/// use ratatui::{backend::Backend, layout::Position};
@@ -241,7 +241,7 @@ pub trait Backend {
///
/// # Example
///
/// ```rust,no_run
/// ```rust,ignore
/// # use ratatui::backend::{TestBackend};
/// # let mut backend = TestBackend::new(80, 25);
/// use ratatui::backend::Backend;
@@ -259,7 +259,7 @@ pub trait Backend {
///
/// # Example
///
/// ```rust,no_run
/// ```rust,ignore
/// # use ratatui::{backend::{TestBackend}};
/// # let mut backend = TestBackend::new(80, 25);
/// use ratatui::backend::{Backend, ClearType};
@@ -293,7 +293,7 @@ pub trait Backend {
///
/// # Example
///
/// ```rust
/// ```rust,ignore
/// # use ratatui::{backend::{TestBackend}};
/// # let backend = TestBackend::new(80, 25);
/// use ratatui::{backend::Backend, layout::Size};

View File

@@ -23,7 +23,7 @@ use crate::{
///
/// # Example
///
/// ```rust
/// ```rust,ignore
/// use ratatui::backend::{Backend, TestBackend};
///
/// let mut backend = TestBackend::new(10, 2);

View File

@@ -345,7 +345,7 @@ impl Buffer {
let max_width = max_width.try_into().unwrap_or(u16::MAX);
let mut remaining_width = self.area.right().saturating_sub(x).min(max_width);
let graphemes = UnicodeSegmentation::graphemes(string.as_ref(), true)
.filter(|symbol| !symbol.contains(|char: char| char.is_control()))
.filter(|symbol| !symbol.contains(char::is_control))
.map(|symbol| (symbol, symbol.width() as u16))
.filter(|(_symbol, width)| *width > 0)
.map_while(|(symbol, width)| {

View File

@@ -40,6 +40,16 @@ pub struct Offset {
pub y: i32,
}
impl Offset {
/// A zero offset
pub const ZERO: Self = Self { x: 0, y: 0 };
/// Creates a new `Offset` with the given values.
pub const fn new(x: i32, y: i32) -> Self {
Self { x, y }
}
}
impl fmt::Display for Rect {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}x{}+{}+{}", self.width, self.height, self.x, self.y)

View File

@@ -43,5 +43,6 @@ pub mod buffer;
pub mod layout;
pub mod style;
pub mod symbols;
pub mod terminal;
pub mod text;
pub mod widgets;

View File

@@ -79,6 +79,8 @@ pub use color::{Color, ParseColorError};
use stylize::ColorDebugKind;
pub use stylize::{Styled, Stylize};
#[cfg(feature = "anstyle")]
mod anstyle;
mod color;
pub mod palette;
#[cfg(feature = "palette")]

View File

@@ -0,0 +1,331 @@
//! This module contains conversion functions for styles from the `anstyle` crate.
use anstyle::{Ansi256Color, AnsiColor, Effects, RgbColor};
use thiserror::Error;
use super::{Color, Modifier, Style};
/// Error type for converting between `anstyle` colors and `Color`
#[derive(Debug, Error, PartialEq, Eq)]
pub enum TryFromColorError {
#[error("cannot convert Ratatui Color to an Ansi256Color as it is not an indexed color")]
Ansi256,
#[error("cannot convert Ratatui Color to AnsiColor as it is not a 4-bit color")]
Ansi,
#[error("cannot convert Ratatui Color to RgbColor as it is not an RGB color")]
RgbColor,
}
impl From<Ansi256Color> for Color {
fn from(color: Ansi256Color) -> Self {
Self::Indexed(color.index())
}
}
impl TryFrom<Color> for Ansi256Color {
type Error = TryFromColorError;
fn try_from(color: Color) -> Result<Self, Self::Error> {
match color {
Color::Indexed(index) => Ok(Self(index)),
_ => Err(TryFromColorError::Ansi256),
}
}
}
impl From<AnsiColor> for Color {
fn from(value: AnsiColor) -> Self {
match value {
AnsiColor::Black => Self::Black,
AnsiColor::Red => Self::Red,
AnsiColor::Green => Self::Green,
AnsiColor::Yellow => Self::Yellow,
AnsiColor::Blue => Self::Blue,
AnsiColor::Magenta => Self::Magenta,
AnsiColor::Cyan => Self::Cyan,
AnsiColor::White => Self::Gray,
AnsiColor::BrightBlack => Self::DarkGray,
AnsiColor::BrightRed => Self::LightRed,
AnsiColor::BrightGreen => Self::LightGreen,
AnsiColor::BrightYellow => Self::LightYellow,
AnsiColor::BrightBlue => Self::LightBlue,
AnsiColor::BrightMagenta => Self::LightMagenta,
AnsiColor::BrightCyan => Self::LightCyan,
AnsiColor::BrightWhite => Self::White,
}
}
}
impl TryFrom<Color> for AnsiColor {
type Error = TryFromColorError;
fn try_from(color: Color) -> Result<Self, Self::Error> {
match color {
Color::Black => Ok(Self::Black),
Color::Red => Ok(Self::Red),
Color::Green => Ok(Self::Green),
Color::Yellow => Ok(Self::Yellow),
Color::Blue => Ok(Self::Blue),
Color::Magenta => Ok(Self::Magenta),
Color::Cyan => Ok(Self::Cyan),
Color::Gray => Ok(Self::White),
Color::DarkGray => Ok(Self::BrightBlack),
Color::LightRed => Ok(Self::BrightRed),
Color::LightGreen => Ok(Self::BrightGreen),
Color::LightYellow => Ok(Self::BrightYellow),
Color::LightBlue => Ok(Self::BrightBlue),
Color::LightMagenta => Ok(Self::BrightMagenta),
Color::LightCyan => Ok(Self::BrightCyan),
Color::White => Ok(Self::BrightWhite),
_ => Err(TryFromColorError::Ansi),
}
}
}
impl From<RgbColor> for Color {
fn from(color: RgbColor) -> Self {
Self::Rgb(color.r(), color.g(), color.b())
}
}
impl TryFrom<Color> for RgbColor {
type Error = TryFromColorError;
fn try_from(color: Color) -> Result<Self, Self::Error> {
match color {
Color::Rgb(red, green, blue) => Ok(Self(red, green, blue)),
_ => Err(TryFromColorError::RgbColor),
}
}
}
impl From<anstyle::Color> for Color {
fn from(color: anstyle::Color) -> Self {
match color {
anstyle::Color::Ansi(ansi_color) => Self::from(ansi_color),
anstyle::Color::Ansi256(ansi256_color) => Self::from(ansi256_color),
anstyle::Color::Rgb(rgb_color) => Self::from(rgb_color),
}
}
}
impl From<Color> for anstyle::Color {
fn from(color: Color) -> Self {
match color {
Color::Rgb(_, _, _) => Self::Rgb(RgbColor::try_from(color).unwrap()),
Color::Indexed(_) => Self::Ansi256(Ansi256Color::try_from(color).unwrap()),
_ => Self::Ansi(AnsiColor::try_from(color).unwrap()),
}
}
}
impl From<Effects> for Modifier {
fn from(effect: Effects) -> Self {
let mut modifier = Self::empty();
if effect.contains(Effects::BOLD) {
modifier |= Self::BOLD;
}
if effect.contains(Effects::DIMMED) {
modifier |= Self::DIM;
}
if effect.contains(Effects::ITALIC) {
modifier |= Self::ITALIC;
}
if effect.contains(Effects::UNDERLINE)
|| effect.contains(Effects::DOUBLE_UNDERLINE)
|| effect.contains(Effects::CURLY_UNDERLINE)
|| effect.contains(Effects::DOTTED_UNDERLINE)
|| effect.contains(Effects::DASHED_UNDERLINE)
{
modifier |= Self::UNDERLINED;
}
if effect.contains(Effects::BLINK) {
modifier |= Self::SLOW_BLINK;
}
if effect.contains(Effects::INVERT) {
modifier |= Self::REVERSED;
}
if effect.contains(Effects::HIDDEN) {
modifier |= Self::HIDDEN;
}
if effect.contains(Effects::STRIKETHROUGH) {
modifier |= Self::CROSSED_OUT;
}
modifier
}
}
impl From<Modifier> for Effects {
fn from(modifier: Modifier) -> Self {
let mut effects = Self::new();
if modifier.contains(Modifier::BOLD) {
effects |= Self::BOLD;
}
if modifier.contains(Modifier::DIM) {
effects |= Self::DIMMED;
}
if modifier.contains(Modifier::ITALIC) {
effects |= Self::ITALIC;
}
if modifier.contains(Modifier::UNDERLINED) {
effects |= Self::UNDERLINE;
}
if modifier.contains(Modifier::SLOW_BLINK) || modifier.contains(Modifier::RAPID_BLINK) {
effects |= Self::BLINK;
}
if modifier.contains(Modifier::REVERSED) {
effects |= Self::INVERT;
}
if modifier.contains(Modifier::HIDDEN) {
effects |= Self::HIDDEN;
}
if modifier.contains(Modifier::CROSSED_OUT) {
effects |= Self::STRIKETHROUGH;
}
effects
}
}
impl From<anstyle::Style> for Style {
fn from(style: anstyle::Style) -> Self {
Self {
fg: style.get_fg_color().map(Color::from),
bg: style.get_bg_color().map(Color::from),
add_modifier: style.get_effects().into(),
..Default::default()
}
}
}
impl From<Style> for anstyle::Style {
fn from(style: Style) -> Self {
let mut anstyle_style = Self::new();
if let Some(fg) = style.fg {
let fg = anstyle::Color::from(fg);
anstyle_style = anstyle_style.fg_color(Some(fg));
}
if let Some(bg) = style.bg {
let bg = anstyle::Color::from(bg);
anstyle_style = anstyle_style.bg_color(Some(bg));
}
anstyle_style = anstyle_style.effects(style.add_modifier.into());
anstyle_style
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn anstyle_to_color() {
let anstyle_color = Ansi256Color(42);
let color = Color::from(anstyle_color);
assert_eq!(color, Color::Indexed(42));
}
#[test]
fn color_to_ansi256color() {
let color = Color::Indexed(42);
let anstyle_color = Ansi256Color::try_from(color);
assert_eq!(anstyle_color, Ok(Ansi256Color(42)));
}
#[test]
fn color_to_ansi256color_error() {
let color = Color::Rgb(0, 0, 0);
let anstyle_color = Ansi256Color::try_from(color);
assert_eq!(anstyle_color, Err(TryFromColorError::Ansi256));
}
#[test]
fn ansi_color_to_color() {
let ansi_color = AnsiColor::Red;
let color = Color::from(ansi_color);
assert_eq!(color, Color::Red);
}
#[test]
fn color_to_ansicolor() {
let color = Color::Red;
let ansi_color = AnsiColor::try_from(color);
assert_eq!(ansi_color, Ok(AnsiColor::Red));
}
#[test]
fn color_to_ansicolor_error() {
let color = Color::Rgb(0, 0, 0);
let ansi_color = AnsiColor::try_from(color);
assert_eq!(ansi_color, Err(TryFromColorError::Ansi));
}
#[test]
fn rgb_color_to_color() {
let rgb_color = RgbColor(255, 0, 0);
let color = Color::from(rgb_color);
assert_eq!(color, Color::Rgb(255, 0, 0));
}
#[test]
fn color_to_rgbcolor() {
let color = Color::Rgb(255, 0, 0);
let rgb_color = RgbColor::try_from(color);
assert_eq!(rgb_color, Ok(RgbColor(255, 0, 0)));
}
#[test]
fn color_to_rgbcolor_error() {
let color = Color::Indexed(42);
let rgb_color = RgbColor::try_from(color);
assert_eq!(rgb_color, Err(TryFromColorError::RgbColor));
}
#[test]
fn effects_to_modifier() {
let effects = Effects::BOLD | Effects::ITALIC;
let modifier = Modifier::from(effects);
assert!(modifier.contains(Modifier::BOLD));
assert!(modifier.contains(Modifier::ITALIC));
}
#[test]
fn modifier_to_effects() {
let modifier = Modifier::BOLD | Modifier::ITALIC;
let effects = Effects::from(modifier);
assert!(effects.contains(Effects::BOLD));
assert!(effects.contains(Effects::ITALIC));
}
#[test]
fn anstyle_style_to_style() {
let anstyle_style = anstyle::Style::new()
.fg_color(Some(anstyle::Color::Ansi(AnsiColor::Red)))
.bg_color(Some(anstyle::Color::Ansi(AnsiColor::Blue)))
.effects(Effects::BOLD | Effects::ITALIC);
let style = Style::from(anstyle_style);
assert_eq!(style.fg, Some(Color::Red));
assert_eq!(style.bg, Some(Color::Blue));
assert!(style.add_modifier.contains(Modifier::BOLD));
assert!(style.add_modifier.contains(Modifier::ITALIC));
}
#[test]
fn style_to_anstyle_style() {
let style = Style {
fg: Some(Color::Red),
bg: Some(Color::Blue),
add_modifier: Modifier::BOLD | Modifier::ITALIC,
..Default::default()
};
let anstyle_style = anstyle::Style::from(style);
assert_eq!(
anstyle_style.get_fg_color(),
Some(anstyle::Color::Ansi(AnsiColor::Red))
);
assert_eq!(
anstyle_style.get_bg_color(),
Some(anstyle::Color::Ansi(AnsiColor::Blue))
);
assert!(anstyle_style.get_effects().contains(Effects::BOLD));
assert!(anstyle_style.get_effects().contains(Effects::ITALIC));
}
}

View File

@@ -250,7 +250,7 @@ pub trait Stylize<'a, T>: Sized {
modifier!(crossed_out);
}
impl<'a, T, U> Stylize<'a, T> for U
impl<T, U> Stylize<'_, T> for U
where
U: Styled<Item = T>,
{

View File

@@ -1,238 +1,13 @@
//! Symbols and markers for drawing various widgets.
use strum::{Display, EnumString};
pub use marker::{Marker, DOT};
pub mod bar;
pub mod block;
pub mod border;
pub mod braille;
pub mod half_block;
pub mod line;
pub mod block {
pub const FULL: &str = "";
pub const SEVEN_EIGHTHS: &str = "";
pub const THREE_QUARTERS: &str = "";
pub const FIVE_EIGHTHS: &str = "";
pub const HALF: &str = "";
pub const THREE_EIGHTHS: &str = "";
pub const ONE_QUARTER: &str = "";
pub const ONE_EIGHTH: &str = "";
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Set {
pub full: &'static str,
pub seven_eighths: &'static str,
pub three_quarters: &'static str,
pub five_eighths: &'static str,
pub half: &'static str,
pub three_eighths: &'static str,
pub one_quarter: &'static str,
pub one_eighth: &'static str,
pub empty: &'static str,
}
impl Default for Set {
fn default() -> Self {
NINE_LEVELS
}
}
pub const THREE_LEVELS: Set = Set {
full: FULL,
seven_eighths: FULL,
three_quarters: HALF,
five_eighths: HALF,
half: HALF,
three_eighths: HALF,
one_quarter: HALF,
one_eighth: " ",
empty: " ",
};
pub const NINE_LEVELS: Set = Set {
full: FULL,
seven_eighths: SEVEN_EIGHTHS,
three_quarters: THREE_QUARTERS,
five_eighths: FIVE_EIGHTHS,
half: HALF,
three_eighths: THREE_EIGHTHS,
one_quarter: ONE_QUARTER,
one_eighth: ONE_EIGHTH,
empty: " ",
};
}
pub mod half_block {
pub const UPPER: char = '▀';
pub const LOWER: char = '▄';
pub const FULL: char = '█';
}
pub mod bar {
pub const FULL: &str = "";
pub const SEVEN_EIGHTHS: &str = "";
pub const THREE_QUARTERS: &str = "";
pub const FIVE_EIGHTHS: &str = "";
pub const HALF: &str = "";
pub const THREE_EIGHTHS: &str = "";
pub const ONE_QUARTER: &str = "";
pub const ONE_EIGHTH: &str = "";
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Set {
pub full: &'static str,
pub seven_eighths: &'static str,
pub three_quarters: &'static str,
pub five_eighths: &'static str,
pub half: &'static str,
pub three_eighths: &'static str,
pub one_quarter: &'static str,
pub one_eighth: &'static str,
pub empty: &'static str,
}
impl Default for Set {
fn default() -> Self {
NINE_LEVELS
}
}
pub const THREE_LEVELS: Set = Set {
full: FULL,
seven_eighths: FULL,
three_quarters: HALF,
five_eighths: HALF,
half: HALF,
three_eighths: HALF,
one_quarter: HALF,
one_eighth: " ",
empty: " ",
};
pub const NINE_LEVELS: Set = Set {
full: FULL,
seven_eighths: SEVEN_EIGHTHS,
three_quarters: THREE_QUARTERS,
five_eighths: FIVE_EIGHTHS,
half: HALF,
three_eighths: THREE_EIGHTHS,
one_quarter: ONE_QUARTER,
one_eighth: ONE_EIGHTH,
empty: " ",
};
}
pub const DOT: &str = "";
pub mod braille {
pub const BLANK: u16 = 0x2800;
pub const DOTS: [[u16; 2]; 4] = [
[0x0001, 0x0008],
[0x0002, 0x0010],
[0x0004, 0x0020],
[0x0040, 0x0080],
];
}
/// Marker to use when plotting data points
#[derive(Debug, Default, Display, EnumString, Clone, Copy, Eq, PartialEq, Hash)]
pub enum Marker {
/// One point per cell in shape of dot (`•`)
#[default]
Dot,
/// One point per cell in shape of a block (`█`)
Block,
/// One point per cell in the shape of a bar (`▄`)
Bar,
/// Use the [Unicode Braille Patterns](https://en.wikipedia.org/wiki/Braille_Patterns) block to
/// represent data points.
///
/// This is a 2x4 grid of dots, where each dot can be either on or off.
///
/// Note: Support for this marker is limited to terminals and fonts that support Unicode
/// Braille Patterns. If your terminal does not support this, you will see unicode replacement
/// characters (`<60>`) instead of Braille dots (`⠓`, `⣇`, `⣿`).
Braille,
/// Use the unicode block and half block characters (`█`, `▄`, and `▀`) to represent points in
/// a grid that is double the resolution of the terminal. Because each terminal cell is
/// generally about twice as tall as it is wide, this allows for a square grid of pixels.
HalfBlock,
}
pub mod scrollbar {
use crate::symbols::{block, line};
/// Scrollbar Set
/// ```text
/// <--▮------->
/// ^ ^ ^ ^
/// │ │ │ └ end
/// │ │ └──── track
/// │ └──────── thumb
/// └─────────── begin
/// ```
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
pub struct Set {
pub track: &'static str,
pub thumb: &'static str,
pub begin: &'static str,
pub end: &'static str,
}
pub const DOUBLE_VERTICAL: Set = Set {
track: line::DOUBLE_VERTICAL,
thumb: block::FULL,
begin: "",
end: "",
};
pub const DOUBLE_HORIZONTAL: Set = Set {
track: line::DOUBLE_HORIZONTAL,
thumb: block::FULL,
begin: "",
end: "",
};
pub const VERTICAL: Set = Set {
track: line::VERTICAL,
thumb: block::FULL,
begin: "",
end: "",
};
pub const HORIZONTAL: Set = Set {
track: line::HORIZONTAL,
thumb: block::FULL,
begin: "",
end: "",
};
}
pub mod shade {
pub const EMPTY: &str = " ";
pub const LIGHT: &str = "";
pub const MEDIUM: &str = "";
pub const DARK: &str = "";
pub const FULL: &str = "";
}
#[cfg(test)]
mod tests {
use strum::ParseError;
use super::*;
#[test]
fn marker_tostring() {
assert_eq!(Marker::Dot.to_string(), "Dot");
assert_eq!(Marker::Block.to_string(), "Block");
assert_eq!(Marker::Bar.to_string(), "Bar");
assert_eq!(Marker::Braille.to_string(), "Braille");
}
#[test]
fn marker_from_str() {
assert_eq!("Dot".parse::<Marker>(), Ok(Marker::Dot));
assert_eq!("Block".parse::<Marker>(), Ok(Marker::Block));
assert_eq!("Bar".parse::<Marker>(), Ok(Marker::Bar));
assert_eq!("Braille".parse::<Marker>(), Ok(Marker::Braille));
assert_eq!("".parse::<Marker>(), Err(ParseError::VariantNotFound));
}
}
pub mod marker;
pub mod scrollbar;
pub mod shade;

View File

@@ -0,0 +1,51 @@
pub const FULL: &str = "";
pub const SEVEN_EIGHTHS: &str = "";
pub const THREE_QUARTERS: &str = "";
pub const FIVE_EIGHTHS: &str = "";
pub const HALF: &str = "";
pub const THREE_EIGHTHS: &str = "";
pub const ONE_QUARTER: &str = "";
pub const ONE_EIGHTH: &str = "";
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Set {
pub full: &'static str,
pub seven_eighths: &'static str,
pub three_quarters: &'static str,
pub five_eighths: &'static str,
pub half: &'static str,
pub three_eighths: &'static str,
pub one_quarter: &'static str,
pub one_eighth: &'static str,
pub empty: &'static str,
}
impl Default for Set {
fn default() -> Self {
NINE_LEVELS
}
}
pub const THREE_LEVELS: Set = Set {
full: FULL,
seven_eighths: FULL,
three_quarters: HALF,
five_eighths: HALF,
half: HALF,
three_eighths: HALF,
one_quarter: HALF,
one_eighth: " ",
empty: " ",
};
pub const NINE_LEVELS: Set = Set {
full: FULL,
seven_eighths: SEVEN_EIGHTHS,
three_quarters: THREE_QUARTERS,
five_eighths: FIVE_EIGHTHS,
half: HALF,
three_eighths: THREE_EIGHTHS,
one_quarter: ONE_QUARTER,
one_eighth: ONE_EIGHTH,
empty: " ",
};

View File

@@ -0,0 +1,51 @@
pub const FULL: &str = "";
pub const SEVEN_EIGHTHS: &str = "";
pub const THREE_QUARTERS: &str = "";
pub const FIVE_EIGHTHS: &str = "";
pub const HALF: &str = "";
pub const THREE_EIGHTHS: &str = "";
pub const ONE_QUARTER: &str = "";
pub const ONE_EIGHTH: &str = "";
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Set {
pub full: &'static str,
pub seven_eighths: &'static str,
pub three_quarters: &'static str,
pub five_eighths: &'static str,
pub half: &'static str,
pub three_eighths: &'static str,
pub one_quarter: &'static str,
pub one_eighth: &'static str,
pub empty: &'static str,
}
impl Default for Set {
fn default() -> Self {
NINE_LEVELS
}
}
pub const THREE_LEVELS: Set = Set {
full: FULL,
seven_eighths: FULL,
three_quarters: HALF,
five_eighths: HALF,
half: HALF,
three_eighths: HALF,
one_quarter: HALF,
one_eighth: " ",
empty: " ",
};
pub const NINE_LEVELS: Set = Set {
full: FULL,
seven_eighths: SEVEN_EIGHTHS,
three_quarters: THREE_QUARTERS,
five_eighths: FIVE_EIGHTHS,
half: HALF,
three_eighths: THREE_EIGHTHS,
one_quarter: ONE_QUARTER,
one_eighth: ONE_EIGHTH,
empty: " ",
};

View File

@@ -0,0 +1,7 @@
pub const BLANK: u16 = 0x2800;
pub const DOTS: [[u16; 2]; 4] = [
[0x0001, 0x0008],
[0x0002, 0x0010],
[0x0004, 0x0020],
[0x0040, 0x0080],
];

View File

@@ -0,0 +1,3 @@
pub const UPPER: char = '▀';
pub const LOWER: char = '▄';
pub const FULL: char = '█';

View File

@@ -0,0 +1,52 @@
use strum::{Display, EnumString};
pub const DOT: &str = "";
/// Marker to use when plotting data points
#[derive(Debug, Default, Display, EnumString, Clone, Copy, Eq, PartialEq, Hash)]
pub enum Marker {
/// One point per cell in shape of dot (`•`)
#[default]
Dot,
/// One point per cell in shape of a block (`█`)
Block,
/// One point per cell in the shape of a bar (`▄`)
Bar,
/// Use the [Unicode Braille Patterns](https://en.wikipedia.org/wiki/Braille_Patterns) block to
/// represent data points.
///
/// This is a 2x4 grid of dots, where each dot can be either on or off.
///
/// Note: Support for this marker is limited to terminals and fonts that support Unicode
/// Braille Patterns. If your terminal does not support this, you will see unicode replacement
/// characters (`<60>`) instead of Braille dots (`⠓`, `⣇`, `⣿`).
Braille,
/// Use the unicode block and half block characters (`█`, `▄`, and `▀`) to represent points in
/// a grid that is double the resolution of the terminal. Because each terminal cell is
/// generally about twice as tall as it is wide, this allows for a square grid of pixels.
HalfBlock,
}
#[cfg(test)]
mod tests {
use strum::ParseError;
use super::*;
#[test]
fn marker_tostring() {
assert_eq!(Marker::Dot.to_string(), "Dot");
assert_eq!(Marker::Block.to_string(), "Block");
assert_eq!(Marker::Bar.to_string(), "Bar");
assert_eq!(Marker::Braille.to_string(), "Braille");
}
#[test]
fn marker_from_str() {
assert_eq!("Dot".parse::<Marker>(), Ok(Marker::Dot));
assert_eq!("Block".parse::<Marker>(), Ok(Marker::Block));
assert_eq!("Bar".parse::<Marker>(), Ok(Marker::Bar));
assert_eq!("Braille".parse::<Marker>(), Ok(Marker::Braille));
assert_eq!("".parse::<Marker>(), Err(ParseError::VariantNotFound));
}
}

View File

@@ -0,0 +1,46 @@
use crate::symbols::{block, line};
/// Scrollbar Set
/// ```text
/// <--▮------->
/// ^ ^ ^ ^
/// │ │ │ └ end
/// │ │ └──── track
/// │ └──────── thumb
/// └─────────── begin
/// ```
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
pub struct Set {
pub track: &'static str,
pub thumb: &'static str,
pub begin: &'static str,
pub end: &'static str,
}
pub const DOUBLE_VERTICAL: Set = Set {
track: line::DOUBLE_VERTICAL,
thumb: block::FULL,
begin: "",
end: "",
};
pub const DOUBLE_HORIZONTAL: Set = Set {
track: line::DOUBLE_HORIZONTAL,
thumb: block::FULL,
begin: "",
end: "",
};
pub const VERTICAL: Set = Set {
track: line::VERTICAL,
thumb: block::FULL,
begin: "",
end: "",
};
pub const HORIZONTAL: Set = Set {
track: line::HORIZONTAL,
thumb: block::FULL,
begin: "",
end: "",
};

View File

@@ -0,0 +1,5 @@
pub const EMPTY: &str = " ";
pub const LIGHT: &str = "";
pub const MEDIUM: &str = "";
pub const DARK: &str = "";
pub const FULL: &str = "";

View File

@@ -10,7 +10,7 @@
//!
//! # Example
//!
//! ```rust,no_run
//! ```rust,ignore
//! use std::io::stdout;
//!
//! use ratatui::{backend::CrosstermBackend, widgets::Paragraph, Terminal};
@@ -32,15 +32,9 @@
//! [`Buffer`]: crate::buffer::Buffer
mod frame;
#[cfg(feature = "crossterm")]
mod init;
mod terminal;
mod viewport;
pub use frame::{CompletedFrame, Frame};
#[cfg(feature = "crossterm")]
pub use init::{
init, init_with_options, restore, try_init, try_init_with_options, try_restore, DefaultTerminal,
};
pub use terminal::{Options as TerminalOptions, Terminal};
pub use viewport::Viewport;

View File

@@ -1,7 +1,7 @@
use crate::{
buffer::Buffer,
layout::{Position, Rect},
widgets::{StatefulWidget, StatefulWidgetRef, Widget, WidgetRef},
widgets::{StatefulWidget, Widget},
};
/// A consistent view into the terminal state for rendering a single frame.
@@ -14,7 +14,7 @@ use crate::{
/// to the terminal. This avoids drawing redundant cells.
///
/// [`Buffer`]: crate::buffer::Buffer
/// [`Terminal::draw`]: crate::Terminal::draw
/// [`Terminal::draw`]: crate::terminal::Terminal::draw
#[derive(Debug, Hash)]
pub struct Frame<'a> {
/// Where should the cursor be after drawing this frame?
@@ -37,7 +37,7 @@ pub struct Frame<'a> {
/// [`Terminal::draw`] call have been applied. Therefore, it is only valid until the next call to
/// [`Terminal::draw`].
///
/// [`Terminal::draw`]: crate::Terminal::draw
/// [`Terminal::draw`]: crate::terminal::Terminal::draw
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct CompletedFrame<'a> {
/// The buffer that was used to draw the last frame.
@@ -79,7 +79,7 @@ impl Frame<'_> {
///
/// # Example
///
/// ```rust
/// ```rust,ignore
/// # use ratatui::{backend::TestBackend, Terminal};
/// # let backend = TestBackend::new(5, 5);
/// # let mut terminal = Terminal::new(backend).unwrap();
@@ -96,32 +96,6 @@ impl Frame<'_> {
widget.render(area, self.buffer);
}
/// Render a [`WidgetRef`] to the current buffer using [`WidgetRef::render_ref`].
///
/// Usually the area argument is the size of the current frame or a sub-area of the current
/// frame (which can be obtained using [`Layout`] to split the total area).
///
/// # Example
///
/// ```rust
/// # #[cfg(feature = "unstable-widget-ref")] {
/// # use ratatui::{backend::TestBackend, Terminal};
/// # let backend = TestBackend::new(5, 5);
/// # let mut terminal = Terminal::new(backend).unwrap();
/// # let mut frame = terminal.get_frame();
/// use ratatui::{layout::Rect, widgets::Block};
///
/// let block = Block::new();
/// let area = Rect::new(0, 0, 5, 5);
/// frame.render_widget_ref(&block, area);
/// # }
/// ```
#[allow(clippy::needless_pass_by_value)]
#[instability::unstable(feature = "widget-ref")]
pub fn render_widget_ref<W: WidgetRef>(&mut self, widget: W, area: Rect) {
widget.render_ref(area, self.buffer);
}
/// Render a [`StatefulWidget`] to the current buffer using [`StatefulWidget::render`].
///
/// Usually the area argument is the size of the current frame or a sub-area of the current
@@ -132,7 +106,7 @@ impl Frame<'_> {
///
/// # Example
///
/// ```rust
/// ```rust,ignore
/// # use ratatui::{backend::TestBackend, Terminal};
/// # let backend = TestBackend::new(5, 5);
/// # let mut terminal = Terminal::new(backend).unwrap();
@@ -156,43 +130,6 @@ impl Frame<'_> {
widget.render(area, self.buffer, state);
}
/// Render a [`StatefulWidgetRef`] to the current buffer using
/// [`StatefulWidgetRef::render_ref`].
///
/// Usually the area argument is the size of the current frame or a sub-area of the current
/// frame (which can be obtained using [`Layout`] to split the total area).
///
/// The last argument should be an instance of the [`StatefulWidgetRef::State`] associated to
/// the given [`StatefulWidgetRef`].
///
/// # Example
///
/// ```rust
/// # #[cfg(feature = "unstable-widget-ref")] {
/// # use ratatui::{backend::TestBackend, Terminal};
/// # let backend = TestBackend::new(5, 5);
/// # let mut terminal = Terminal::new(backend).unwrap();
/// # let mut frame = terminal.get_frame();
/// use ratatui::{
/// layout::Rect,
/// widgets::{List, ListItem, ListState},
/// };
///
/// let mut state = ListState::default().with_selected(Some(1));
/// let list = List::new(vec![ListItem::new("Item 1"), ListItem::new("Item 2")]);
/// let area = Rect::new(0, 0, 5, 5);
/// frame.render_stateful_widget_ref(&list, area, &mut state);
/// # }
/// ```
#[allow(clippy::needless_pass_by_value)]
#[instability::unstable(feature = "widget-ref")]
pub fn render_stateful_widget_ref<W>(&mut self, widget: W, area: Rect, state: &mut W::State)
where
W: StatefulWidgetRef,
{
widget.render_ref(area, self.buffer, state);
}
/// After drawing this frame, make the cursor visible and put it at the specified (x, y)
/// coordinates. If this method is not called, the cursor will be hidden.
///
@@ -200,9 +137,9 @@ impl Frame<'_> {
/// [`Terminal::show_cursor`], and [`Terminal::set_cursor_position`]. Pick one of the APIs and
/// stick with it.
///
/// [`Terminal::hide_cursor`]: crate::Terminal::hide_cursor
/// [`Terminal::show_cursor`]: crate::Terminal::show_cursor
/// [`Terminal::set_cursor_position`]: crate::Terminal::set_cursor_position
/// [`Terminal::hide_cursor`]: crate::terminal::Terminal::hide_cursor
/// [`Terminal::show_cursor`]: crate::terminal::Terminal::show_cursor
/// [`Terminal::set_cursor_position`]: crate::terminal::Terminal::set_cursor_position
pub fn set_cursor_position<P: Into<Position>>(&mut self, position: P) {
self.cursor_position = Some(position.into());
}
@@ -214,9 +151,9 @@ impl Frame<'_> {
/// [`Terminal::show_cursor`], and [`Terminal::set_cursor_position`]. Pick one of the APIs and
/// stick with it.
///
/// [`Terminal::hide_cursor`]: crate::Terminal::hide_cursor
/// [`Terminal::show_cursor`]: crate::Terminal::show_cursor
/// [`Terminal::set_cursor_position`]: crate::Terminal::set_cursor_position
/// [`Terminal::hide_cursor`]: crate::terminal::Terminal::hide_cursor
/// [`Terminal::show_cursor`]: crate::terminal::Terminal::show_cursor
/// [`Terminal::set_cursor_position`]: crate::terminal::Terminal::set_cursor_position
#[deprecated = "the method set_cursor_position indicates more clearly what about the cursor to set"]
pub fn set_cursor(&mut self, x: u16, y: u16) {
self.set_cursor_position(Position { x, y });
@@ -243,7 +180,7 @@ impl Frame<'_> {
///
/// # Examples
///
/// ```rust
/// ```rust,ignore
/// # use ratatui::{backend::TestBackend, Terminal};
/// # let backend = TestBackend::new(5, 5);
/// # let mut terminal = Terminal::new(backend).unwrap();

View File

@@ -1,11 +1,10 @@
use std::io;
use ratatui_core::backend::{Backend, ClearType};
use crate::{
backend::{Backend, ClearType},
buffer::{Buffer, Cell},
layout::{Position, Rect, Size},
CompletedFrame, Frame, TerminalOptions, Viewport,
terminal::{CompletedFrame, Frame, TerminalOptions, Viewport},
};
/// An interface to interact and draw [`Frame`]s on the user's terminal.
@@ -33,7 +32,7 @@ use crate::{
///
/// # Examples
///
/// ```rust,no_run
/// ```rust,ignore
/// use std::io::stdout;
///
/// use ratatui::{backend::CrosstermBackend, widgets::Paragraph, Terminal};
@@ -109,7 +108,7 @@ where
///
/// # Example
///
/// ```rust,no_run
/// ```rust,ignore
/// use std::io::stdout;
///
/// use ratatui::{backend::CrosstermBackend, Terminal};
@@ -131,7 +130,7 @@ where
///
/// # Example
///
/// ```rust
/// ```rust,ignore
/// use std::io::stdout;
///
/// use ratatui::{backend::CrosstermBackend, layout::Rect, Terminal, TerminalOptions, Viewport};
@@ -282,7 +281,7 @@ where
///
/// # Examples
///
/// ```
/// ```rust,ignore
/// # let backend = ratatui::backend::TestBackend::new(10, 10);
/// # let mut terminal = ratatui::Terminal::new(backend)?;
/// use ratatui::{layout::Position, widgets::Paragraph};
@@ -350,7 +349,7 @@ where
///
/// # Examples
///
/// ```should_panic
/// ```ignore
/// # use ratatui::layout::Position;;
/// # let backend = ratatui::backend::TestBackend::new(10, 10);
/// # let mut terminal = ratatui::Terminal::new(backend)?;
@@ -558,7 +557,7 @@ where
///
/// ## Insert a single line before the current viewport
///
/// ```rust
/// ```rust,ignore
/// use ratatui::{
/// backend::TestBackend,
/// style::{Color, Style},

View File

@@ -15,7 +15,7 @@ use crate::layout::Rect;
///
/// See [`Terminal::with_options`] for more information.
///
/// [`Terminal::with_options`]: crate::Terminal::with_options
/// [`Terminal::with_options`]: crate::terminal::Terminal::with_options
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
pub enum Viewport {
/// The viewport is fullscreen

View File

@@ -34,7 +34,7 @@ impl<'a> StyledGrapheme<'a> {
}
}
impl<'a> Styled for StyledGrapheme<'a> {
impl Styled for StyledGrapheme<'_> {
type Item = Self;
fn style(&self) -> Style {

6
ratatui-core/src/text/line.rs Executable file → Normal file
View File

@@ -599,7 +599,7 @@ impl<'a> IntoIterator for &'a mut Line<'a> {
}
}
impl<'a> From<String> for Line<'a> {
impl From<String> for Line<'_> {
fn from(s: String) -> Self {
Self::raw(s)
}
@@ -753,7 +753,7 @@ fn render_spans(spans: &[Span], mut area: Rect, buf: &mut Buffer, span_skip_widt
}
}
/// Returns an iterator over the spans that lie after a given skip widtch from the start of the
/// Returns an iterator over the spans that lie after a given skip width from the start of the
/// `Line` (including a partially visible span if the `skip_width` lands within a span).
fn spans_after_width<'a>(
spans: &'a [Span],
@@ -830,7 +830,7 @@ impl fmt::Display for Line<'_> {
}
}
impl<'a> Styled for Line<'a> {
impl Styled for Line<'_> {
type Item = Self;
fn style(&self) -> Style {

View File

@@ -322,7 +322,7 @@ impl<'a> Span<'a> {
self.content
.as_ref()
.graphemes(true)
.filter(|g| *g != "\n")
.filter(|g| !g.contains(char::is_control))
.map(move |g| StyledGrapheme { symbol: g, style })
}
@@ -404,7 +404,7 @@ impl<'a> std::ops::Add<Self> for Span<'a> {
}
}
impl<'a> Styled for Span<'a> {
impl Styled for Span<'_> {
type Item = Self;
fn style(&self) -> Style {

8
ratatui-core/src/text/text.rs Executable file → Normal file
View File

@@ -598,7 +598,7 @@ impl<'a> IntoIterator for &'a mut Text<'a> {
}
}
impl<'a> From<String> for Text<'a> {
impl From<String> for Text<'_> {
fn from(s: String) -> Self {
Self::raw(s)
}
@@ -668,7 +668,7 @@ impl<'a> std::ops::Add<Line<'a>> for Text<'a> {
/// Adds two `Text` together.
///
/// This ignores the style and alignment of the second `Text`.
impl<'a> std::ops::Add<Self> for Text<'a> {
impl std::ops::Add<Self> for Text<'_> {
type Output = Self;
fn add(mut self, text: Self) -> Self::Output {
@@ -730,7 +730,7 @@ impl fmt::Display for Text<'_> {
impl Widget for Text<'_> {
fn render(self, area: Rect, buf: &mut Buffer) {
Widget::render(&self, area, buf)
Widget::render(&self, area, buf);
}
}
@@ -744,7 +744,7 @@ impl Widget for &Text<'_> {
}
}
impl<'a> Styled for Text<'a> {
impl Styled for Text<'_> {
type Item = Self;
fn style(&self) -> Style {

View File

@@ -1,6 +1,6 @@
[package]
name = "ratatui-crossterm"
version = "0.1.0-alpha.0"
version = "0.1.0-alpha.1"
description = "Crossterm backend for the Ratatui Terminal UI library."
documentation = "https://docs.rs/ratatui-crossterm/"
readme = "README.md"
@@ -18,8 +18,7 @@ rust-version.workspace = true
default = ["underline-color"]
## enables the backend code that sets the underline color.
## Underline color is only supported by the [`CrosstermBackend`](backend::CrosstermBackend) backend,
## and is not supported on Windows 7.
## Underline color is not supported on Windows 7.
underline-color = ["ratatui-core/underline-color"]
## Use terminal scrolling regions to make Terminal::insert_before less prone to flickering.
@@ -43,3 +42,6 @@ ratatui-core = { workspace = true }
[dev-dependencies]
ratatui = { path = "../ratatui", features = ["crossterm"] }
rstest.workspace = true
[lints]
workspace = true

View File

@@ -405,11 +405,19 @@ impl ModifierDiff {
if removed.contains(Modifier::REVERSED) {
queue!(w, SetAttribute(CrosstermAttribute::NoReverse))?;
}
if removed.contains(Modifier::BOLD) {
if removed.contains(Modifier::BOLD) || removed.contains(Modifier::DIM) {
// Bold and Dim are both reset by applying the Normal intensity
queue!(w, SetAttribute(CrosstermAttribute::NormalIntensity))?;
// The remaining Bold and Dim attributes must be
// reapplied after the intensity reset above.
if self.to.contains(Modifier::DIM) {
queue!(w, SetAttribute(CrosstermAttribute::Dim))?;
}
if self.to.contains(Modifier::BOLD) {
queue!(w, SetAttribute(CrosstermAttribute::Bold))?;
}
}
if removed.contains(Modifier::ITALIC) {
queue!(w, SetAttribute(CrosstermAttribute::NoItalic))?;
@@ -417,9 +425,6 @@ impl ModifierDiff {
if removed.contains(Modifier::UNDERLINED) {
queue!(w, SetAttribute(CrosstermAttribute::NoUnderline))?;
}
if removed.contains(Modifier::DIM) {
queue!(w, SetAttribute(CrosstermAttribute::NormalIntensity))?;
}
if removed.contains(Modifier::CROSSED_OUT) {
queue!(w, SetAttribute(CrosstermAttribute::NotCrossedOut))?;
}

View File

@@ -1,6 +1,6 @@
[package]
name = "ratatui-termion"
version = "0.1.0-alpha.0"
version = "0.1.0-alpha.1"
description = "Termion backend for the Ratatui Terminal UI library."
documentation = "https://docs.rs/ratatui-termion/"
readme = "README.md"
@@ -21,15 +21,21 @@ rustdoc-args = ["--cfg", "docsrs"]
[features]
default = []
## Use terminal scrolling regions to make Terminal::insert_before less prone to flickering.
scrolling-regions = ["ratatui-core/scrolling-regions"]
## Enables all unstable features.
unstable = ["unstable-backend-writer"]
## Enables getting access to backends' writer.
unstable-backend-writer = []
[dependencies]
document-features = { workspace = true, optional = true }
instability.workspace = true
ratatui-core = { workspace = true }
termion.workspace = true
instability.workspace = true
[dev-dependencies]
rstest.workspace = true
[lints]
workspace = true

View File

@@ -72,7 +72,7 @@ use termion::{color as tcolor, color::Color as _, style as tstyle};
///
/// [`IntoRawMode::into_raw_mode()`]: termion::raw::IntoRawMode
/// [`IntoAlternateScreen::into_alternate_screen()`]: termion::screen::IntoAlternateScreen
/// [`Terminal`]: ratatui::terminal::Terminal
/// [`Terminal`]: ratatui_core::terminal::Terminal
/// [Termion]: https://docs.rs/termion
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
pub struct TermionBackend<W>

View File

@@ -1,6 +1,6 @@
[package]
name = "ratatui-termwiz"
version = "0.1.0-alpha.0"
version = "0.1.0-alpha.1"
description = "Termwiz backend for the Ratatui Terminal UI library."
documentation = "https://docs.rs/ratatui-termwiz/"
readme = "README.md"
@@ -37,3 +37,6 @@ termwiz.workspace = true
[dev-dependencies]
ratatui = { path = "../ratatui", features = ["termwiz"] }
rstest.workspace = true
[lints]
workspace = true

View File

@@ -3,7 +3,7 @@ name = "ratatui-widgets"
description = "A collection of Ratatui widgets for building terminal user interfaces using Ratatui."
# Note that this started at 0.3.0 as there was a previous crate using the name `ratatui-widgets`.
# <https://github.com/joshka/ratatui-widgets/issues/46>
version = "0.3.0-alpha.0"
version = "0.3.0-alpha.1"
readme = "README.md"
authors.workspace = true
documentation.workspace = true
@@ -48,17 +48,17 @@ unstable-rendered-line-info = []
[dependencies]
bitflags.workspace = true
itertools.workspace = true
document-features = { workspace = true, optional = true }
indoc.workspace = true
instability.workspace = true
itertools.workspace = true
line-clipping = "0.2.1"
ratatui-core = { workspace = true }
serde = { workspace = true, optional = true }
strum.workspace = true
time = { version = "0.3.11", optional = true, features = ["local-offset"] }
unicode-segmentation.workspace = true
unicode-width.workspace = true
serde = { workspace = true, optional = true }
document-features = { workspace = true, optional = true }
line-clipping = "0.2.1"
[dev-dependencies]
color-eyre.workspace = true
@@ -66,52 +66,10 @@ pretty_assertions.workspace = true
ratatui = { path = "../ratatui" }
rstest.workspace = true
[lints.rust]
unsafe_code = "forbid"
[lints.clippy]
cargo = { level = "warn", priority = -1 }
pedantic = { level = "warn", priority = -1 }
cast_possible_truncation = "allow"
cast_possible_wrap = "allow"
cast_precision_loss = "allow"
cast_sign_loss = "allow"
missing_errors_doc = "allow"
missing_panics_doc = "allow"
module_name_repetitions = "allow"
must_use_candidate = "allow"
# we often split up a module into multiple files with the main type in a file named after the
# module, so we want to allow this pattern
module_inception = "allow"
# nursery or restricted
as_underscore = "warn"
deref_by_slicing = "warn"
else_if_without_else = "warn"
empty_line_after_doc_comments = "warn"
equatable_if_let = "warn"
fn_to_numeric_cast_any = "warn"
format_push_string = "warn"
map_err_ignore = "warn"
missing_const_for_fn = "warn"
mixed_read_write_in_expression = "warn"
mod_module_files = "warn"
needless_pass_by_ref_mut = "warn"
needless_raw_strings = "warn"
or_fun_call = "warn"
redundant_type_annotations = "warn"
rest_pat_in_fully_bound_structs = "warn"
string_lit_chars_any = "warn"
string_slice = "warn"
string_to_string = "warn"
unnecessary_self_imports = "warn"
use_self = "warn"
[lints]
workspace = true
# Adding a single example is enough for activating rustdoc-scrape-examples
[[example]]
name = "barchart"
doc-scrape-examples = true
[[example]]
name = "block"
doc-scrape-examples = true

View File

@@ -44,6 +44,7 @@ cargo add ratatui-widgets
- [`LineGauge`]: displays progress as a line.
- [`List`]: displays a list of items and allows selection.
- [`RatatuiLogo`]: displays the Ratatui logo.
- [`RatatuiMascot`]: displays the Ratatui mascot.
- [`Paragraph`]: displays a paragraph of optionally styled and wrapped text.
- [`Scrollbar`]: displays a scrollbar.
- [`Sparkline`]: displays a single dataset as a sparkline.
@@ -60,6 +61,7 @@ cargo add ratatui-widgets
[`LineGauge`]: https://docs.rs/ratatui-widgets/latest/ratatui_widgets/gauge/struct.LineGauge.html
[`List`]: https://docs.rs/ratatui-widgets/latest/ratatui_widgets/list/struct.List.html
[`RatatuiLogo`]: https://docs.rs/ratatui-widgets/latest/ratatui_widgets/logo/struct.RatatuiLogo.html
[`RatatuiMascot`]: https://docs.rs/ratatui-widgets/latest/ratatui_widgets/mascot/struct.RatatuiMascot.html
[`Paragraph`]: https://docs.rs/ratatui-widgets/latest/ratatui_widgets/paragraph/struct.Paragraph.html
[`Scrollbar`]: https://docs.rs/ratatui-widgets/latest/ratatui_widgets/scrollbar/struct.Scrollbar.html
[`Sparkline`]: https://docs.rs/ratatui-widgets/latest/ratatui_widgets/sparkline/struct.Sparkline.html

View File

@@ -0,0 +1,103 @@
//! # [Ratatui] `BarChart` example with grouped bars
//!
//! The latest version of this example is available in the [widget examples] folder in the
//! repository.
//!
//! Please note that the examples are designed to be run against the `main` branch of the Github
//! repository. This means that you may not be able to compile with the latest release version on
//! crates.io, or the one that you have installed locally.
//!
//! See the [examples readme] for more information on finding examples that match the version of the
//! library you are using.
//!
//! [Ratatui]: https://github.com/ratatui/ratatui
//! [widget examples]: https://github.com/ratatui/ratatui/blob/main/ratatui-widgets/examples
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
use std::iter::zip;
use color_eyre::Result;
use ratatui::{
crossterm::event::{self, Event},
layout::{Constraint, Direction, Layout, Rect},
style::{Color, Stylize},
text::{Line, Span},
widgets::{Bar, BarChart, BarGroup},
DefaultTerminal, Frame,
};
fn main() -> Result<()> {
color_eyre::install()?;
let terminal = ratatui::init();
let result = run(terminal);
ratatui::restore();
result
}
/// Run the application.
fn run(mut terminal: DefaultTerminal) -> Result<()> {
loop {
terminal.draw(draw)?;
if matches!(event::read()?, Event::Key(_)) {
break Ok(());
}
}
}
/// Draw the UI with a barchart on the left and right side.
fn draw(frame: &mut Frame) {
let vertical = Layout::vertical([Constraint::Length(1), Constraint::Fill(1)]).spacing(1);
let horizontal = Layout::horizontal([Constraint::Fill(1); 2]).spacing(1);
let [top, main] = vertical.areas(frame.area());
let [left, right] = horizontal.areas(main);
let title = Line::from_iter([
Span::from("BarChart Widget (Grouped)").bold(),
Span::from(" (Press 'q' to quit)"),
]);
frame.render_widget(title.centered(), top);
render_barchart(frame, left, Direction::Vertical, 6);
render_barchart(frame, right, Direction::Horizontal, 1);
}
/// Render a barchart with grouped bars.
fn render_barchart(frame: &mut Frame, area: Rect, direction: Direction, bar_width: u16) {
let companies = [
("BITE", Color::Blue),
("TART", Color::White),
("BAKE", Color::LightRed),
];
let revenues = [
("Jan", [8500, 6500, 7000]),
("Feb", [9000, 7500, 8500]),
("Mar", [9500, 4500, 8200]),
("Apr", [6300, 4000, 5000]),
];
let mut barchart = BarChart::default()
.bar_gap(0)
.bar_width(bar_width)
.group_gap(2)
.direction(direction);
for (period, values) in revenues {
let bars: Vec<_> = zip(companies, values)
.map(|((label, color), value)| bar(label, value, color))
.collect();
let label = Line::from(period).centered();
let group = BarGroup::new(bars).label(label);
barchart = barchart.data(group);
}
frame.render_widget(barchart, area);
}
/// Return a bar with the given label, value, and color.
fn bar(label: &str, value: u64, color: Color) -> Bar<'_> {
Bar::default()
.label(label)
.value(value)
.text_value(format!("{:.1}M", value as f64 / 1000.))
.style(color)
.value_style((Color::Black, color))
}

View File

@@ -16,6 +16,7 @@
use color_eyre::Result;
use ratatui::{
crossterm::event::{self, Event},
layout::{Constraint, Layout, Rect},
style::Stylize,
text::{Line, Span},
@@ -35,7 +36,7 @@ fn main() -> Result<()> {
fn run(mut terminal: DefaultTerminal) -> Result<()> {
loop {
terminal.draw(draw)?;
if quit_key_pressed()? {
if matches!(event::read()?, Event::Key(_)) {
break Ok(());
}
}
@@ -80,12 +81,3 @@ fn render_vertical_barchart(frame: &mut Frame, area: Rect) {
let chart = BarChart::vertical(bars).bar_width(6);
frame.render_widget(chart, area);
}
/// Wait for an event and return `true` if the Esc or 'q' key is pressed.
fn quit_key_pressed() -> Result<bool> {
use ratatui::crossterm::event::{self, Event, KeyCode};
match event::read()? {
Event::Key(event) if matches!(event.code, KeyCode::Esc | KeyCode::Char('q')) => Ok(true),
_ => Ok(false),
}
}

View File

@@ -0,0 +1,92 @@
//! # [Ratatui] `Calendar` example
//!
//! The latest version of this example is available in the [widget examples] folder in the
//! repository.
//!
//! Please note that the examples are designed to be run against the `main` branch of the Github
//! repository. This means that you may not be able to compile with the latest release version on
//! crates.io, or the one that you have installed locally.
//!
//! See the [examples readme] for more information on finding examples that match the version of the
//! library you are using.
//!
//! [Ratatui]: https://github.com/ratatui/ratatui
//! [widget examples]: https://github.com/ratatui/ratatui/blob/main/ratatui-widgets/examples
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
use color_eyre::Result;
use ratatui::{
crossterm::event::{self, Event},
layout::{Constraint, Layout, Rect},
style::{Color, Modifier, Style, Stylize},
text::{Line, Span},
widgets::{Block, Padding},
DefaultTerminal, Frame,
};
use ratatui_widgets::calendar::{CalendarEventStore, Monthly};
use time::{Date, Month, OffsetDateTime};
fn main() -> Result<()> {
color_eyre::install()?;
let terminal = ratatui::init();
let result = run(terminal);
ratatui::restore();
result
}
/// Run the application.
fn run(mut terminal: DefaultTerminal) -> Result<()> {
loop {
terminal.draw(draw)?;
if matches!(event::read()?, Event::Key(_)) {
break Ok(());
}
}
}
/// Draw the UI with 2 monthly calendars side by side.
fn draw(frame: &mut Frame) {
let vertical = Layout::vertical([Constraint::Length(1), Constraint::Fill(1)]).spacing(1);
let horizontal = Layout::horizontal([Constraint::Percentage(50); 2]).spacing(1);
let [top, main] = vertical.areas(frame.area());
let [left, right] = horizontal.areas(main);
let title = Line::from_iter([
Span::from("Calendar Widget").bold(),
Span::from(" (Press 'q' to quit)"),
]);
frame.render_widget(title.centered(), top);
render_current_month(frame, left);
render_styled_month(frame, right);
}
/// Render the current month calendar.
fn render_current_month(frame: &mut Frame, area: Rect) {
let date = OffsetDateTime::now_utc().date();
let monthly = Monthly::new(
date,
CalendarEventStore::today(Style::default().red().bold()),
)
.block(Block::new().padding(Padding::new(0, 0, 2, 0)))
.show_month_header(Modifier::BOLD)
.show_weekdays_header(Modifier::ITALIC);
frame.render_widget(monthly, area);
}
/// Render an arbitrary month with more styles.
fn render_styled_month(frame: &mut Frame, area: Rect) {
// Release date of the movie Ratatouille.
let date = Date::from_calendar_date(2007, Month::June, 29).unwrap();
let mut event_store = CalendarEventStore::today(Style::default().red().bold());
event_store.add(date, Style::default().blue().italic());
let monthly = Monthly::new(date, event_store)
.show_surrounding(Modifier::DIM)
.show_month_header(Modifier::BOLD)
.show_weekdays_header(Style::default().bold().green())
.default_style(Style::default().bold().bg(Color::Rgb(50, 50, 50)));
frame.render_widget(monthly, area);
}

View File

@@ -0,0 +1,95 @@
//! # [Ratatui] `Canvas` example
//!
//! The latest version of this example is available in the [widget examples] folder in the
//! repository.
//!
//! Please note that the examples are designed to be run against the `main` branch of the Github
//! repository. This means that you may not be able to compile with the latest release version on
//! crates.io, or the one that you have installed locally.
//!
//! See the [examples readme] for more information on finding examples that match the version of the
//! library you are using.
//!
//! [Ratatui]: https://github.com/ratatui/ratatui
//! [widget examples]: https://github.com/ratatui/ratatui/blob/main/ratatui-widgets/examples
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
use color_eyre::Result;
use ratatui::{
crossterm::event::{self, Event},
layout::{Constraint, Layout, Rect},
style::{Color, Stylize},
symbols::Marker,
text::{Line as TextLine, Span},
widgets::canvas::{Canvas, Line, Map, MapResolution, Rectangle},
DefaultTerminal, Frame,
};
use ratatui_widgets::canvas::Points;
fn main() -> Result<()> {
color_eyre::install()?;
let terminal = ratatui::init();
let result = run(terminal);
ratatui::restore();
result
}
/// Run the application.
fn run(mut terminal: DefaultTerminal) -> Result<()> {
loop {
terminal.draw(draw)?;
if matches!(event::read()?, Event::Key(_)) {
break Ok(());
}
}
}
/// Draw the UI with a canvas widget.
fn draw(frame: &mut Frame) {
let vertical = Layout::vertical([Constraint::Length(1), Constraint::Fill(1)]).spacing(1);
let horizontal = Layout::horizontal([Constraint::Percentage(100)]).spacing(1);
let [top, main] = vertical.areas(frame.area());
let [area] = horizontal.areas(main);
let title = TextLine::from_iter([
Span::from("Canvas Widget").bold(),
Span::from(" (Press 'q' to quit)"),
]);
frame.render_widget(title.centered(), top);
render_canvas(frame, area);
}
/// Renders the canvas widget with various shapes and a map.
pub fn render_canvas(frame: &mut Frame, area: Rect) {
let canvas = Canvas::default()
.x_bounds([-180.0, 180.0])
.y_bounds([-90.0, 90.0])
.marker(Marker::Braille)
.paint(|ctx| {
ctx.draw(&Map {
resolution: MapResolution::High,
color: Color::White,
});
ctx.layer();
ctx.draw(&Line::new(0.0, 10.0, 10.0, 10.0, Color::Blue));
ctx.draw(&Rectangle {
x: 10.0,
y: 20.0,
width: 10.0,
height: 10.0,
color: Color::Green,
});
ctx.draw(&Points {
coords: &[
(2.3522, 48.8566), // Paris
(-122.3321, 47.6062), // Seattle
(-79.3837, 43.6511), // Toronto
(32.8597, 39.9334), // Ankara
],
color: Color::Red,
});
});
frame.render_widget(canvas, area);
}

View File

@@ -0,0 +1,92 @@
//! # [Ratatui] `Chart` example
//!
//! The latest version of this example is available in the [widget examples] folder in the
//! repository.
//!
//! Please note that the examples are designed to be run against the `main` branch of the Github
//! repository. This means that you may not be able to compile with the latest release version on
//! crates.io, or the one that you have installed locally.
//!
//! See the [examples readme] for more information on finding examples that match the version of the
//! library you are using.
//!
//! [Ratatui]: https://github.com/ratatui/ratatui
//! [widget examples]: https://github.com/ratatui/ratatui/blob/main/ratatui-widgets/examples
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
use color_eyre::Result;
use ratatui::{
crossterm::event::{self, Event},
layout::{Constraint, Layout, Rect},
style::{Color, Stylize},
symbols::Marker,
text::{Line, Span},
widgets::{Axis, Chart, Dataset, GraphType},
DefaultTerminal, Frame,
};
fn main() -> Result<()> {
color_eyre::install()?;
let terminal = ratatui::init();
let result = run(terminal);
ratatui::restore();
result
}
/// Run the application.
fn run(mut terminal: DefaultTerminal) -> Result<()> {
loop {
terminal.draw(draw)?;
if matches!(event::read()?, Event::Key(_)) {
break Ok(());
}
}
}
/// Draw the UI with a chart.
fn draw(frame: &mut Frame) {
let vertical = Layout::vertical([Constraint::Length(1), Constraint::Fill(1)]).spacing(1);
let [top, main] = vertical.areas(frame.area());
let title = Line::from_iter([
Span::from("Chart Widget").bold(),
Span::from(" (Press 'q' to quit)"),
]);
frame.render_widget(title.centered(), top);
render_chart(frame, main);
}
/// Render a chart going upward.
pub fn render_chart(frame: &mut Frame, area: Rect) {
let dataset = Dataset::default()
.name("Stonks")
.marker(Marker::Braille)
.graph_type(GraphType::Line)
.style(Color::Blue)
.data(&[
(0.0, 1.0),
(1.0, 3.0),
(2.0, 0.5),
(3.0, 2.0),
(4.0, 0.8),
(5.0, 4.0),
(6.0, 1.0),
(7.0, 6.0),
(8.0, 3.0),
(10.0, 10.0),
]);
let x_axis = Axis::default()
.title("Hustle".blue())
.bounds([0.0, 10.0])
.labels(["0%", "50%", "100%"]);
let y_axis = Axis::default()
.title("Profit".blue())
.bounds([0.0, 10.0])
.labels(["0", "5", "10"]);
let chart = Chart::new(vec![dataset]).x_axis(x_axis).y_axis(y_axis);
frame.render_widget(chart, area);
}

View File

@@ -0,0 +1,85 @@
//! # [Ratatui] `Gauge` example
//!
//! The latest version of this example is available in the [widget examples] folder in the
//! repository.
//!
//! Please note that the examples are designed to be run against the `main` branch of the Github
//! repository. This means that you may not be able to compile with the latest release version on
//! crates.io, or the one that you have installed locally.
//!
//! See the [examples readme] for more information on finding examples that match the version of the
//! library you are using.
//!
//! [Ratatui]: https://github.com/ratatui/ratatui
//! [widget examples]: https://github.com/ratatui/ratatui/blob/main/ratatui-widgets/examples
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
use color_eyre::Result;
use ratatui::{
crossterm::event::{self, Event},
layout::{Constraint, Layout, Rect},
style::{Modifier, Style, Stylize},
symbols,
text::{Line, Span},
widgets::{Gauge, LineGauge},
DefaultTerminal, Frame,
};
fn main() -> Result<()> {
color_eyre::install()?;
let terminal = ratatui::init();
let result = run(terminal);
ratatui::restore();
result
}
/// Run the application.
fn run(mut terminal: DefaultTerminal) -> Result<()> {
loop {
terminal.draw(draw)?;
if matches!(event::read()?, Event::Key(_)) {
break Ok(());
}
}
}
/// Draw the UI with various progress bars.
fn draw(frame: &mut Frame) {
let vertical = Layout::vertical([
Constraint::Length(1),
Constraint::Max(2),
Constraint::Fill(1),
])
.spacing(1);
let [top, first, second] = vertical.areas(frame.area());
let title = Line::from_iter([
Span::from("Gauge Widget").bold(),
Span::from(" (Press 'q' to quit)"),
]);
frame.render_widget(title.centered(), top);
render_gauge(frame, first);
render_line_gauge(frame, second);
}
/// Render a gauge with a custom style.
pub fn render_gauge(frame: &mut Frame, area: Rect) {
let gauge = Gauge::default()
.style(Modifier::BOLD)
.gauge_style(Style::new().blue().on_black())
.label("Year Progress")
.percent(80);
frame.render_widget(gauge, area);
}
/// Render a line gauge (compact progress bar).
pub fn render_line_gauge(frame: &mut Frame, area: Rect) {
let line_gauge = LineGauge::default()
.filled_style(Style::new().white().on_red().bold())
.unfilled_style(Style::new().gray().on_black())
.label("❤️ HP")
.ratio(0.42)
.line_set(symbols::line::THICK);
frame.render_widget(line_gauge, area);
}

View File

@@ -0,0 +1,103 @@
//! # [Ratatui] `List` example
//!
//! The latest version of this example is available in the [widget examples] folder in the
//! repository.
//!
//! Please note that the examples are designed to be run against the `main` branch of the Github
//! repository. This means that you may not be able to compile with the latest release version on
//! crates.io, or the one that you have installed locally.
//!
//! See the [examples readme] for more information on finding examples that match the version of the
//! library you are using.
//!
//! [Ratatui]: https://github.com/ratatui/ratatui
//! [widget examples]: https://github.com/ratatui/ratatui/blob/main/ratatui-widgets/examples
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
use color_eyre::Result;
use ratatui::{
crossterm::event::{self, Event, KeyCode},
layout::{Constraint, Layout, Rect},
style::{Color, Modifier, Style, Stylize},
text::{Line, Span},
widgets::{List, ListDirection, ListState},
DefaultTerminal, Frame,
};
fn main() -> Result<()> {
color_eyre::install()?;
let terminal = ratatui::init();
let result = run(terminal);
ratatui::restore();
result
}
/// Run the application.
fn run(mut terminal: DefaultTerminal) -> Result<()> {
let mut list_state = ListState::default();
list_state.select_first();
loop {
terminal.draw(|frame| draw(frame, &mut list_state))?;
if let Event::Key(key) = event::read()? {
match key.code {
KeyCode::Char('q') => break Ok(()),
KeyCode::Down | KeyCode::Char('j') => list_state.select_next(),
KeyCode::Up | KeyCode::Char('k') => list_state.select_previous(),
_ => {}
}
}
}
}
/// Draw the UI with various lists.
fn draw(frame: &mut Frame, list_state: &mut ListState) {
let vertical = Layout::vertical([
Constraint::Length(1),
Constraint::Fill(1),
Constraint::Fill(1),
])
.spacing(1);
let [top, first, second] = vertical.areas(frame.area());
let title = Line::from_iter([
Span::from("List Widget").bold(),
Span::from(" (Press 'q' to quit and arrow keys to navigate)"),
]);
frame.render_widget(title.centered(), top);
render_list(frame, first, list_state);
render_bottom_list(frame, second);
}
/// Render a list.
pub fn render_list(frame: &mut Frame, area: Rect, list_state: &mut ListState) {
let items = ["Item 1", "Item 2", "Item 3", "Item 4"];
let list = List::new(items)
.style(Color::White)
.highlight_style(Modifier::REVERSED)
.highlight_symbol("> ");
frame.render_stateful_widget(list, area, list_state);
}
/// Render a bottom-to-top list.
pub fn render_bottom_list(frame: &mut Frame, area: Rect) {
let items = [
"[Remy]: I'm building one now.\nIt even supports multiline text!",
"[Gusteau]: With enough passion, yes.",
"[Remy]: But can anyone build a TUI in Rust?",
"[Gusteau]: Anyone can cook!",
];
let list = List::new(items)
.style(Color::White)
.highlight_style(Style::new().yellow().italic())
.highlight_symbol("> ")
.scroll_padding(1)
.direction(ListDirection::BottomToTop)
.repeat_highlight_symbol(true);
let mut state = ListState::default();
state.select_first();
frame.render_stateful_widget(list, area, &mut state);
}

View File

@@ -1,6 +1,7 @@
//! # [Ratatui] Logo example
//! # [Ratatui] `RatatuiLogo` example
//!
//! The latest version of this example is available in the [examples] folder in the repository.
//! The latest version of this example is available in the [widget examples] folder in the
//! repository.
//!
//! Please note that the examples are designed to be run against the `main` branch of the Github
//! repository. This means that you may not be able to compile with the latest release version on
@@ -10,17 +11,17 @@
//! library you are using.
//!
//! [Ratatui]: https://github.com/ratatui/ratatui
//! [examples]: https://github.com/ratatui/ratatui/blob/main/examples
//! [widget examples]: https://github.com/ratatui/ratatui/blob/main/ratatui-widgets/examples
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
use std::env::args;
use color_eyre::Result;
use crossterm::event::{self, Event};
use ratatui::{
crossterm::event::{self, Event},
layout::{Constraint, Layout},
widgets::{RatatuiLogo, RatatuiLogoSize},
DefaultTerminal, TerminalOptions, Viewport,
DefaultTerminal, Frame, TerminalOptions, Viewport,
};
fn main() -> Result<()> {
@@ -39,16 +40,21 @@ fn main() -> Result<()> {
result
}
/// Run the application.
fn run(mut terminal: DefaultTerminal, size: RatatuiLogoSize) -> Result<()> {
loop {
terminal.draw(|frame| {
use Constraint::{Fill, Length};
let [top, bottom] = Layout::vertical([Length(1), Fill(1)]).areas(frame.area());
frame.render_widget("Powered by", top);
frame.render_widget(RatatuiLogo::new(size), bottom);
})?;
terminal.draw(|frame| draw(frame, size))?;
if matches!(event::read()?, Event::Key(_)) {
break Ok(());
}
}
}
/// Draw the UI with a logo.
fn draw(frame: &mut Frame, size: RatatuiLogoSize) {
let [top, bottom] =
Layout::vertical([Constraint::Length(1), Constraint::Fill(1)]).areas(frame.area());
frame.render_widget("Powered by", top);
frame.render_widget(RatatuiLogo::new(size), bottom);
}

View File

@@ -0,0 +1,102 @@
//! # [Ratatui] `Paragraph` example
//!
//! The latest version of this example is available in the [widget examples] folder in the
//! repository.
//!
//! Please note that the examples are designed to be run against the `main` branch of the Github
//! repository. This means that you may not be able to compile with the latest release version on
//! crates.io, or the one that you have installed locally.
//!
//! See the [examples readme] for more information on finding examples that match the version of the
//! library you are using.
//!
//! [Ratatui]: https://github.com/ratatui/ratatui
//! [widget examples]: https://github.com/ratatui/ratatui/blob/main/ratatui-widgets/examples
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
use color_eyre::Result;
use ratatui::{
crossterm::event::{self, Event},
layout::{Alignment, Constraint, Layout, Rect},
style::{Color, Stylize},
text::{Line, Masked, Span},
widgets::{Paragraph, Wrap},
DefaultTerminal, Frame,
};
fn main() -> Result<()> {
color_eyre::install()?;
let terminal = ratatui::init();
let result = run(terminal);
ratatui::restore();
result
}
/// Run the application.
fn run(mut terminal: DefaultTerminal) -> Result<()> {
loop {
terminal.draw(draw)?;
if matches!(event::read()?, Event::Key(_)) {
break Ok(());
}
}
}
/// Draw the UI with various text.
fn draw(frame: &mut Frame) {
let vertical = Layout::vertical([Constraint::Length(1), Constraint::Fill(1)]).spacing(1);
let horizontal = Layout::horizontal([Constraint::Percentage(50); 2]).spacing(1);
let [top, main] = vertical.areas(frame.area());
let [first, second] = horizontal.areas(main);
let title = Line::from_iter([
Span::from("Paragraph Widget").bold(),
Span::from(" (Press 'q' to quit)"),
]);
frame.render_widget(title.centered(), top);
render_centered_paragraph(frame, first);
render_wrapped_paragraph(frame, second);
}
/// Render a paragraph with centered text.
pub fn render_centered_paragraph(frame: &mut Frame, area: Rect) {
let text = "Centered text\nwith multiple lines.\nCheck out the recipe!";
let paragraph = Paragraph::new(text)
.style(Color::White)
.alignment(Alignment::Center);
frame.render_widget(paragraph, area);
}
/// Render a long paragraph that wraps text.
pub fn render_wrapped_paragraph(frame: &mut Frame, area: Rect) {
let paragraph = Paragraph::new(create_lines(area))
.style(Color::White)
.scroll((0, 0))
.wrap(Wrap { trim: true });
frame.render_widget(paragraph, area);
}
/// Returns the lines for the paragraph.
fn create_lines(area: Rect) -> Vec<Line<'static>> {
let short_line = "Slice, layer, and bake the vegetables. ";
let long_line = short_line.repeat((area.width as usize) / short_line.len() + 2);
vec![
"Recipe: Ratatouille".into(),
"Ingredients:".bold().into(),
Line::from_iter([
"Bell Peppers".into(),
", Eggplant".italic(),
", Tomatoes".bold(),
", Onion".into(),
]),
Line::from_iter([
"Secret Ingredient: ".underlined(),
Span::styled(Masked::new("herbs de Provence", '*'), Color::Red),
]),
"Instructions:".bold().yellow().into(),
long_line.green().italic().into(),
]
}

View File

@@ -0,0 +1,133 @@
//! # [Ratatui] `Scrollbar` example
//!
//! The latest version of this example is available in the [widget examples] folder in the
//! repository.
//!
//! Please note that the examples are designed to be run against the `main` branch of the Github
//! repository. This means that you may not be able to compile with the latest release version on
//! crates.io, or the one that you have installed locally.
//!
//! See the [examples readme] for more information on finding examples that match the version of the
//! library you are using.
//!
//! [Ratatui]: https://github.com/ratatui/ratatui
//! [widget examples]: https://github.com/ratatui/ratatui/blob/main/ratatui-widgets/examples
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
use color_eyre::Result;
use ratatui::{
crossterm::event::{self, Event, KeyCode},
layout::{Constraint, Layout, Margin, Rect},
style::{Color, Stylize},
symbols::scrollbar::Set,
text::{Line, Span},
widgets::{Paragraph, Scrollbar, ScrollbarOrientation, ScrollbarState},
DefaultTerminal, Frame,
};
fn main() -> Result<()> {
color_eyre::install()?;
let terminal = ratatui::init();
let result = run(terminal);
ratatui::restore();
result
}
/// Run the application.
fn run(mut terminal: DefaultTerminal) -> Result<()> {
let mut vertical = ScrollbarState::new(100);
let mut horizontal = ScrollbarState::new(100);
loop {
terminal.draw(|frame| draw(frame, &mut vertical, &mut horizontal))?;
if let Event::Key(key) = event::read()? {
match key.code {
KeyCode::Char('q') => break Ok(()),
KeyCode::Down | KeyCode::Char('j') => vertical.next(),
KeyCode::Up | KeyCode::Char('k') => vertical.prev(),
KeyCode::Right | KeyCode::Char('l') => horizontal.next(),
KeyCode::Left | KeyCode::Char('h') => horizontal.prev(),
_ => {}
}
}
}
}
/// Draw the UI with vertical/horizontal scrollbars.
fn draw(frame: &mut Frame, vertical: &mut ScrollbarState, horizontal: &mut ScrollbarState) {
let vertical_layout = Layout::vertical([Constraint::Length(1), Constraint::Fill(1)]).spacing(1);
let [top, main] = vertical_layout.areas(frame.area());
let title = Line::from_iter([
Span::from("Scrollbar Widget").bold(),
Span::from(" (Press 'q' to quit, arrow keys to scroll)"),
]);
frame.render_widget(title.centered(), top);
render_content(frame, main, vertical, horizontal);
render_vertical_scrollbar(frame, main, vertical);
render_horizontal_scrollbar(frame, main, horizontal);
}
/// Render a vertical scrollbar on the right side of the area.
pub fn render_vertical_scrollbar(frame: &mut Frame, area: Rect, vertical: &mut ScrollbarState) {
let scrollbar = Scrollbar::new(ScrollbarOrientation::VerticalRight);
frame.render_stateful_widget(
scrollbar,
area.inner(Margin {
vertical: 1,
horizontal: 0,
}),
vertical,
);
}
/// Render a horizontal scrollbar at the bottom of the area.
pub fn render_horizontal_scrollbar(frame: &mut Frame, area: Rect, horizontal: &mut ScrollbarState) {
let scrollbar = Scrollbar::new(ScrollbarOrientation::HorizontalBottom)
.symbols(Set {
track: "-",
thumb: "",
begin: "<",
end: ">",
})
.track_style(Color::Yellow)
.begin_style(Color::Green)
.end_style(Color::Red);
frame.render_stateful_widget(
scrollbar,
area.inner(Margin {
vertical: 0,
horizontal: 1,
}),
horizontal,
);
}
/// Render some content.
fn render_content(
frame: &mut Frame,
area: Rect,
vertical: &ScrollbarState,
horizontal: &ScrollbarState,
) {
let content = vec![
Line::from("This is a paragraph with a vertical and horizontal scrollbar."),
Line::from_iter(["Lorem ipsum dolor sit amet, consectetur adipiscing elit.".repeat(10)]),
Line::from_iter([
"Horizontal: ".bold(),
horizontal.get_position().to_string().yellow(),
]),
Line::from_iter([
"Vertical: ".bold(),
vertical.get_position().to_string().yellow(),
]),
];
frame.render_widget(
Paragraph::new(content).scroll((
vertical.get_position() as u16,
horizontal.get_position() as u16,
)),
area,
);
}

Some files were not shown because too many files have changed in this diff Show More