iced_selection/lib.rs
1//! A text selection API built around [`iced`]'s [`Paragraph`].
2//!
3//! [`iced`]: https://iced.rs
4//! [`Paragraph`]: https://docs.iced.rs/iced_graphics/text/paragraph/struct.Paragraph.html
5
6#[cfg(feature = "markdown")]
7pub mod markdown;
8pub mod selection;
9pub mod text;
10
11use iced_widget::core;
12use iced_widget::graphics::text::Paragraph;
13#[cfg(feature = "markdown")]
14pub use markdown::view as markdown;
15#[doc(no_inline)]
16pub use text::Text;
17
18/// Creates a new [`Text`] widget with the provided content.
19///
20/// [`Text`]: core::widget::Text
21///
22/// This macro uses the same syntax as [`format!`], but creates a new [`Text`] widget instead.
23///
24/// See [the formatting documentation in `std::fmt`](std::fmt)
25/// for details of the macro argument syntax.
26///
27/// # Examples
28///
29/// ```no_run,ignore
30/// use iced_selection::text;
31///
32/// enum Message {
33/// // ...
34/// }
35///
36/// fn view(_state: &State) -> Element<Message> {
37/// let simple = text!("Hello, world!");
38///
39/// let keyword = text!("Hello, {}", "world!");
40///
41/// let planet = "Earth";
42/// let local_variable = text!("Hello, {planet}!");
43/// // ...
44/// }
45/// ```
46#[macro_export]
47macro_rules! text {
48 ($($arg:tt)*) => {
49 $crate::Text::new(format!($($arg)*))
50 };
51}
52
53/// Creates some [`Rich`] text with the given spans.
54///
55/// # Example
56/// ```no_run,ignore
57/// use iced::font;
58/// use iced_selection::{rich_text, span};
59/// use iced::{color, never, Font};
60///
61/// #[derive(Debug, Clone)]
62/// enum Message {
63/// // ...
64/// }
65///
66/// fn view(state: &State) -> Element<'_, Message> {
67/// rich_text![
68/// span("I am red!").color(color!(0xff0000)),
69/// span(" "),
70/// span("And I am bold!").font(Font { weight: font::Weight::Bold, ..Font::default() }),
71/// ]
72/// .on_link_click(never)
73/// .size(20)
74/// .into()
75/// }
76/// ```
77///
78/// [`Rich`]: crate::text::Rich
79#[macro_export]
80macro_rules! rich_text {
81 () => (
82 $crate::text::Rich::new()
83 );
84 ($($x:expr),+ $(,)?) => (
85 $crate::text::Rich::from_iter([$($crate::text::Span::from($x)),+])
86 );
87}
88
89/// Creates a new [`Span`] of text with the provided content.
90///
91/// A [`Span`] is a fragment of some [`Rich`] text.
92///
93/// This macro uses the same syntax as [`format!`], but creates a new [`Span`] widget instead.
94///
95/// See [the formatting documentation in `std::fmt`](std::fmt)
96/// for details of the macro argument syntax.
97///
98/// # Example
99/// ```no_run,ignore
100/// use iced::font;
101/// use iced_selection::{rich_text, span};
102/// use iced::{color, never, Font};
103///
104/// #[derive(Debug, Clone)]
105/// enum Message {
106/// // ...
107/// }
108///
109/// fn view(state: &State) -> Element<'_, Message> {
110/// rich_text![
111/// span!("I am {}!", red).color(color!(0xff0000)),
112/// " ",
113/// span!("And I am bold!").font(Font { weight: font::Weight::Bold, ..Font::default() }),
114/// ]
115/// .on_link_click(never)
116/// .size(20)
117/// .into()
118/// }
119/// ```
120///
121/// [`Rich`]: crate::text::Rich
122/// [`Span`]: crate::text::Span
123#[macro_export]
124macro_rules! span {
125 ($($arg:tt)*) => {
126 $crate::text::Span::new(format!($($arg)*))
127 };
128}
129
130/// Creates a new [`Text`] widget with the provided content.
131///
132/// # Example
133/// ```no_run,ignore
134/// use iced_selection::text;
135///
136/// enum Message {
137/// // ...
138/// }
139///
140/// fn view(state: &State) -> Element<'_, Message> {
141/// text("Hello, this is iced!")
142/// .size(20)
143/// .into()
144/// }
145/// ```
146pub fn text<'a, Theme, Renderer>(
147 text: impl text::IntoFragment<'a>,
148) -> Text<'a, Theme, Renderer>
149where
150 Theme: text::Catalog + 'a,
151 Renderer: core::text::Renderer,
152{
153 Text::new(text)
154}
155
156/// Creates some [`Rich`] text with the given spans.
157///
158/// [`Rich`]: crate::text::Rich
159///
160/// # Example
161/// ```no_run,ignore
162/// use iced::font;
163/// use iced_selection::{rich_text, span};
164/// use iced::{color, never, Font};
165///
166/// #[derive(Debug, Clone)]
167/// enum Message {
168/// LinkClicked(&'static str),
169/// // ...
170/// }
171///
172/// fn view(state: &State) -> Element<'_, Message> {
173/// rich_text([
174/// span("I am red!").color(color!(0xff0000)),
175/// span(" "),
176/// span("And I am bold!").font(Font { weight: font::Weight::Bold, ..Font::default() }),
177/// ])
178/// .on_link_click(never)
179/// .size(20)
180/// .into()
181/// }
182/// ```
183pub fn rich_text<'a, Link, Message, Theme, Renderer>(
184 spans: impl AsRef<[text::Span<'a, Link, core::Font>]> + 'a,
185) -> text::Rich<'a, Link, Message, Theme, Renderer>
186where
187 Link: Clone + 'static,
188 Theme: text::Catalog + 'a,
189 Renderer: core::text::Renderer<Paragraph = Paragraph, Font = core::Font>,
190{
191 text::Rich::with_spans(spans)
192}
193
194/// Creates a new [`Span`] of text with the provided content.
195///
196/// A [`Span`] is a fragment of some [`Rich`] text.
197///
198/// [`Rich`]: crate::text::Rich
199/// [`Span`]: crate::text::Span
200///
201/// # Example
202/// ```no_run,ignore
203/// use iced::font;
204/// use iced_selection::{rich_text, span};
205/// use iced::{color, never, Font};
206///
207/// #[derive(Debug, Clone)]
208/// enum Message {
209/// // ...
210/// }
211///
212/// fn view(state: &State) -> Element<'_, Message> {
213/// rich_text![
214/// span("I am red!").color(color!(0xff0000)),
215/// " ",
216/// span("And I am bold!").font(Font { weight: font::Weight::Bold, ..Font::default() }),
217/// ]
218/// .on_link_click(never)
219/// .size(20)
220/// .into()
221/// }
222/// ```
223pub fn span<'a, Link>(
224 text: impl text::IntoFragment<'a>,
225) -> text::Span<'a, Link, core::Font> {
226 text::Span::new(text)
227}