nandi/cosmicnimpublic Fork 0
d2c4134
Commits
Clone
git clone https://git.rickub.com/nandi/cosmicnim.git
git clone ssh://git@rickub.com/nandi/cosmicnim.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Write the builder exports longhand

The macro saved four lines each but rustfmt de-indents macro bodies and
leaves the doc comments at column 0. Longhand reads like the header does.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nandithebull committed 2026-09-20T10:11:00-07:00 Browse files
d2c4134 parent: 18ec8fd
modified cosmic_ffi/src/lib.rs +92 -63
@@ -171,39 +171,60 @@ macro_rules! builder {
171171 };
172172 }
173173
174-macro_rules! builder_fn {
175- ($(#[$m:meta])* $name:ident ($b:ident $(, $arg:ident : $ty:ty)*) $body:block) => {
176- $(#[$m])*
177- #[no_mangle]
178- pub unsafe extern "C" fn $name(builder: *mut Builder $(, $arg: $ty)*) {
179- let $b = builder!(builder);
180- $body
181- }
182- };
174+/// Open a vertical container. Close it with `cosmic_end`. Like every builder
175+/// export, a NULL handle makes it a no-op.
176+#[no_mangle]
177+pub unsafe extern "C" fn cosmic_column(b: *mut Builder) {
178+ builder!(b).push(Kind::Column)
179+}
180+
181+/// Open a horizontal container. Close it with `cosmic_end`.
182+#[no_mangle]
183+pub unsafe extern "C" fn cosmic_row(b: *mut Builder) {
184+ builder!(b).push(Kind::Row)
185+}
186+
187+/// Open a plain container. Close it with `cosmic_end`.
188+#[no_mangle]
189+pub unsafe extern "C" fn cosmic_container(b: *mut Builder) {
190+ builder!(b).push(Kind::Container)
191+}
192+
193+/// Close the innermost open container.
194+#[no_mangle]
195+pub unsafe extern "C" fn cosmic_end(b: *mut Builder) {
196+ builder!(b).pop()
197+}
198+
199+/// Gap between the open container's children, in pixels.
200+#[no_mangle]
201+pub unsafe extern "C" fn cosmic_spacing(b: *mut Builder, px: f32) {
202+ builder!(b).top().spacing = px;
203+}
204+
205+/// Inset around the open container's children, in pixels.
206+#[no_mangle]
207+pub unsafe extern "C" fn cosmic_padding(b: *mut Builder, px: f32) {
208+ builder!(b).top().padding = px;
183209 }
184210
185-builder_fn!(/// Open a vertical container. Close it with `cosmic_end`.
186- cosmic_column(b) { b.push(Kind::Column) });
187-builder_fn!(/// Open a horizontal container. Close it with `cosmic_end`.
188- cosmic_row(b) { b.push(Kind::Row) });
189-builder_fn!(/// Open a plain container. Close it with `cosmic_end`.
190- cosmic_container(b) { b.push(Kind::Container) });
191-builder_fn!(/// Close the innermost open container.
192- cosmic_end(b) { b.pop() });
193-
194-builder_fn!(/// Gap between the open container's children, in pixels.
195- cosmic_spacing(b, px: f32) { b.top().spacing = px });
196-builder_fn!(/// Inset around the open container's children, in pixels.
197- cosmic_padding(b, px: f32) { b.top().padding = px });
198-builder_fn!(/// Centre the open container's children across its main axis.
199- cosmic_align_center(b) { b.top().align_center = true });
200-builder_fn!(/// Let the open container take all the space it is offered.
201- cosmic_fill(b) { b.top().fill = true });
202-
203-builder_fn!(/// A blank gap of `w` by `h` pixels.
204- cosmic_space(b, w: f32, h: f32) {
205- b.leaf(widget::Space::new(Length::Fixed(w), Length::Fixed(h)).into())
206- });
211+/// Centre the open container's children across its main axis.
212+#[no_mangle]
213+pub unsafe extern "C" fn cosmic_align_center(b: *mut Builder) {
214+ builder!(b).top().align_center = true;
215+}
216+
217+/// Let the open container take all the space it is offered.
218+#[no_mangle]
219+pub unsafe extern "C" fn cosmic_fill(b: *mut Builder) {
220+ builder!(b).top().fill = true;
221+}
222+
223+/// A blank gap of `w` by `h` pixels.
224+#[no_mangle]
225+pub unsafe extern "C" fn cosmic_space(b: *mut Builder, w: f32, h: f32) {
226+ builder!(b).leaf(widget::Space::new(Length::Fixed(w), Length::Fixed(h)).into())
227+}
207228
208229 /// Text styles for [`cosmic_text`], matching COSMIC's type scale.
209230 pub const TEXT_BODY: i32 = 0;
@@ -215,20 +236,22 @@ pub const TEXT_HEADING: i32 = 5;
215236 pub const TEXT_CAPTION: i32 = 6;
216237 pub const TEXT_MONOTEXT: i32 = 7;
217238
218-builder_fn!(/// A run of text in one of the `COSMIC_TEXT_*` styles.
219- cosmic_text(b, style: i32, text: *const c_char) {
220- let s = str_or(text, "");
221- b.leaf(match style {
222- TEXT_TITLE1 => widget::text::title1(s).into(),
223- TEXT_TITLE2 => widget::text::title2(s).into(),
224- TEXT_TITLE3 => widget::text::title3(s).into(),
225- TEXT_TITLE4 => widget::text::title4(s).into(),
226- TEXT_HEADING => widget::text::heading(s).into(),
227- TEXT_CAPTION => widget::text::caption(s).into(),
228- TEXT_MONOTEXT => widget::text::monotext(s).into(),
229- _ => widget::text::body(s).into(),
230- })
231- });
239+/// A run of text in one of the `TEXT_*` styles.
240+#[no_mangle]
241+pub unsafe extern "C" fn cosmic_text(b: *mut Builder, style: i32, text: *const c_char) {
242+ let b = builder!(b);
243+ let s = str_or(text, "");
244+ b.leaf(match style {
245+ TEXT_TITLE1 => widget::text::title1(s).into(),
246+ TEXT_TITLE2 => widget::text::title2(s).into(),
247+ TEXT_TITLE3 => widget::text::title3(s).into(),
248+ TEXT_TITLE4 => widget::text::title4(s).into(),
249+ TEXT_HEADING => widget::text::heading(s).into(),
250+ TEXT_CAPTION => widget::text::caption(s).into(),
251+ TEXT_MONOTEXT => widget::text::monotext(s).into(),
252+ _ => widget::text::body(s).into(),
253+ })
254+}
232255
233256 /// Button styles for [`cosmic_button`].
234257 pub const BUTTON_STANDARD: i32 = 0;
@@ -237,23 +260,25 @@ pub const BUTTON_DESTRUCTIVE: i32 = 2;
237260 pub const BUTTON_TEXT: i32 = 3;
238261 pub const BUTTON_LINK: i32 = 4;
239262
240-builder_fn!(/// A button that reports `id` to `on_press`. A negative `id`
241- /// makes it inert, which is how a disabled button is expressed.
242- cosmic_button(b, style: i32, label: *const c_char, id: i32) {
243- let s = str_or(label, "");
244- let button = match style {
245- BUTTON_SUGGESTED => widget::button::suggested(s),
246- BUTTON_DESTRUCTIVE => widget::button::destructive(s),
247- BUTTON_TEXT => widget::button::text(s),
248- BUTTON_LINK => widget::button::link(s),
249- _ => widget::button::standard(s),
250- };
251- b.leaf(if id < 0 {
252- button.into()
253- } else {
254- button.on_press(Message::Pressed(id)).into()
255- })
256- });
263+/// A button that reports `id` to `on_press`. A negative `id` makes it inert,
264+/// which is how a disabled button is expressed.
265+#[no_mangle]
266+pub unsafe extern "C" fn cosmic_button(b: *mut Builder, style: i32, label: *const c_char, id: i32) {
267+ let b = builder!(b);
268+ let s = str_or(label, "");
269+ let button = match style {
270+ BUTTON_SUGGESTED => widget::button::suggested(s),
271+ BUTTON_DESTRUCTIVE => widget::button::destructive(s),
272+ BUTTON_TEXT => widget::button::text(s),
273+ BUTTON_LINK => widget::button::link(s),
274+ _ => widget::button::standard(s),
275+ };
276+ b.leaf(if id < 0 {
277+ button.into()
278+ } else {
279+ button.on_press(Message::Pressed(id)).into()
280+ })
281+}
257282
258283 /// Spacing steps for [`cosmic_space_unit`].
259284 pub const SPACE_NONE: i32 = 0;
@@ -387,7 +412,11 @@ pub unsafe extern "C" fn cosmic_run(config: *const CosmicConfig) -> i32 {
387412
388413 let size = cosmic::iced::Size::new(
389414 if c.width == 0 { 420.0 } else { c.width as f32 },
390- if c.height == 0 { 260.0 } else { c.height as f32 },
415+ if c.height == 0 {
416+ 260.0
417+ } else {
418+ c.height as f32
419+ },
391420 );
392421 let settings = cosmic::app::Settings::default().size(size).debug(false);
393422
@@ -171,39 +171,60 @@ macro_rules! builder {
171 };171 };
172 }172 }
173 173
174-macro_rules! builder_fn {174+/// Open a vertical container. Close it with `cosmic_end`. Like every builder
175- ($(#[$m:meta])* $name:ident ($b:ident $(, $arg:ident : $ty:ty)*) $body:block) => {175+/// export, a NULL handle makes it a no-op.
176- $(#[$m])*176+#[no_mangle]
177- #[no_mangle]177+pub unsafe extern "C" fn cosmic_column(b: *mut Builder) {
178- pub unsafe extern "C" fn $name(builder: *mut Builder $(, $arg: $ty)*) {178+ builder!(b).push(Kind::Column)
179- let $b = builder!(builder);179+}
180- $body180+
181- }181+/// Open a horizontal container. Close it with `cosmic_end`.
182- };182+#[no_mangle]
183+pub unsafe extern "C" fn cosmic_row(b: *mut Builder) {
184+ builder!(b).push(Kind::Row)
185+}
186+
187+/// Open a plain container. Close it with `cosmic_end`.
188+#[no_mangle]
189+pub unsafe extern "C" fn cosmic_container(b: *mut Builder) {
190+ builder!(b).push(Kind::Container)
191+}
192+
193+/// Close the innermost open container.
194+#[no_mangle]
195+pub unsafe extern "C" fn cosmic_end(b: *mut Builder) {
196+ builder!(b).pop()
197+}
198+
199+/// Gap between the open container's children, in pixels.
200+#[no_mangle]
201+pub unsafe extern "C" fn cosmic_spacing(b: *mut Builder, px: f32) {
202+ builder!(b).top().spacing = px;
203+}
204+
205+/// Inset around the open container's children, in pixels.
206+#[no_mangle]
207+pub unsafe extern "C" fn cosmic_padding(b: *mut Builder, px: f32) {
208+ builder!(b).top().padding = px;
183 }209 }
184 210
185-builder_fn!(/// Open a vertical container. Close it with `cosmic_end`.211+/// Centre the open container's children across its main axis.
186- cosmic_column(b) { b.push(Kind::Column) });212+#[no_mangle]
187-builder_fn!(/// Open a horizontal container. Close it with `cosmic_end`.213+pub unsafe extern "C" fn cosmic_align_center(b: *mut Builder) {
188- cosmic_row(b) { b.push(Kind::Row) });214+ builder!(b).top().align_center = true;
189-builder_fn!(/// Open a plain container. Close it with `cosmic_end`.215+}
190- cosmic_container(b) { b.push(Kind::Container) });216+
191-builder_fn!(/// Close the innermost open container.217+/// Let the open container take all the space it is offered.
192- cosmic_end(b) { b.pop() });218+#[no_mangle]
193-219+pub unsafe extern "C" fn cosmic_fill(b: *mut Builder) {
194-builder_fn!(/// Gap between the open container's children, in pixels.220+ builder!(b).top().fill = true;
195- cosmic_spacing(b, px: f32) { b.top().spacing = px });221+}
196-builder_fn!(/// Inset around the open container's children, in pixels.222+
197- cosmic_padding(b, px: f32) { b.top().padding = px });223+/// A blank gap of `w` by `h` pixels.
198-builder_fn!(/// Centre the open container's children across its main axis.224+#[no_mangle]
199- cosmic_align_center(b) { b.top().align_center = true });225+pub unsafe extern "C" fn cosmic_space(b: *mut Builder, w: f32, h: f32) {
200-builder_fn!(/// Let the open container take all the space it is offered.226+ builder!(b).leaf(widget::Space::new(Length::Fixed(w), Length::Fixed(h)).into())
201- cosmic_fill(b) { b.top().fill = true });227+}
202-
203-builder_fn!(/// A blank gap of `w` by `h` pixels.
204- cosmic_space(b, w: f32, h: f32) {
205- b.leaf(widget::Space::new(Length::Fixed(w), Length::Fixed(h)).into())
206- });
207 228
208 /// Text styles for [`cosmic_text`], matching COSMIC's type scale.229 /// Text styles for [`cosmic_text`], matching COSMIC's type scale.
209 pub const TEXT_BODY: i32 = 0;230 pub const TEXT_BODY: i32 = 0;
@@ -215,20 +236,22 @@ pub const TEXT_HEADING: i32 = 5;
215 pub const TEXT_CAPTION: i32 = 6;236 pub const TEXT_CAPTION: i32 = 6;
216 pub const TEXT_MONOTEXT: i32 = 7;237 pub const TEXT_MONOTEXT: i32 = 7;
217 238
218-builder_fn!(/// A run of text in one of the `COSMIC_TEXT_*` styles.239+/// A run of text in one of the `TEXT_*` styles.
219- cosmic_text(b, style: i32, text: *const c_char) {240+#[no_mangle]
220- let s = str_or(text, "");241+pub unsafe extern "C" fn cosmic_text(b: *mut Builder, style: i32, text: *const c_char) {
221- b.leaf(match style {242+ let b = builder!(b);
222- TEXT_TITLE1 => widget::text::title1(s).into(),243+ let s = str_or(text, "");
223- TEXT_TITLE2 => widget::text::title2(s).into(),244+ b.leaf(match style {
224- TEXT_TITLE3 => widget::text::title3(s).into(),245+ TEXT_TITLE1 => widget::text::title1(s).into(),
225- TEXT_TITLE4 => widget::text::title4(s).into(),246+ TEXT_TITLE2 => widget::text::title2(s).into(),
226- TEXT_HEADING => widget::text::heading(s).into(),247+ TEXT_TITLE3 => widget::text::title3(s).into(),
227- TEXT_CAPTION => widget::text::caption(s).into(),248+ TEXT_TITLE4 => widget::text::title4(s).into(),
228- TEXT_MONOTEXT => widget::text::monotext(s).into(),249+ TEXT_HEADING => widget::text::heading(s).into(),
229- _ => widget::text::body(s).into(),250+ TEXT_CAPTION => widget::text::caption(s).into(),
230- })251+ TEXT_MONOTEXT => widget::text::monotext(s).into(),
231- });252+ _ => widget::text::body(s).into(),
253+ })
254+}
232 255
233 /// Button styles for [`cosmic_button`].256 /// Button styles for [`cosmic_button`].
234 pub const BUTTON_STANDARD: i32 = 0;257 pub const BUTTON_STANDARD: i32 = 0;
@@ -237,23 +260,25 @@ pub const BUTTON_DESTRUCTIVE: i32 = 2;
237 pub const BUTTON_TEXT: i32 = 3;260 pub const BUTTON_TEXT: i32 = 3;
238 pub const BUTTON_LINK: i32 = 4;261 pub const BUTTON_LINK: i32 = 4;
239 262
240-builder_fn!(/// A button that reports `id` to `on_press`. A negative `id`263+/// A button that reports `id` to `on_press`. A negative `id` makes it inert,
241- /// makes it inert, which is how a disabled button is expressed.264+/// which is how a disabled button is expressed.
242- cosmic_button(b, style: i32, label: *const c_char, id: i32) {265+#[no_mangle]
243- let s = str_or(label, "");266+pub unsafe extern "C" fn cosmic_button(b: *mut Builder, style: i32, label: *const c_char, id: i32) {
244- let button = match style {267+ let b = builder!(b);
245- BUTTON_SUGGESTED => widget::button::suggested(s),268+ let s = str_or(label, "");
246- BUTTON_DESTRUCTIVE => widget::button::destructive(s),269+ let button = match style {
247- BUTTON_TEXT => widget::button::text(s),270+ BUTTON_SUGGESTED => widget::button::suggested(s),
248- BUTTON_LINK => widget::button::link(s),271+ BUTTON_DESTRUCTIVE => widget::button::destructive(s),
249- _ => widget::button::standard(s),272+ BUTTON_TEXT => widget::button::text(s),
250- };273+ BUTTON_LINK => widget::button::link(s),
251- b.leaf(if id < 0 {274+ _ => widget::button::standard(s),
252- button.into()275+ };
253- } else {276+ b.leaf(if id < 0 {
254- button.on_press(Message::Pressed(id)).into()277+ button.into()
255- })278+ } else {
256- });279+ button.on_press(Message::Pressed(id)).into()
280+ })
281+}
257 282
258 /// Spacing steps for [`cosmic_space_unit`].283 /// Spacing steps for [`cosmic_space_unit`].
259 pub const SPACE_NONE: i32 = 0;284 pub const SPACE_NONE: i32 = 0;
@@ -387,7 +412,11 @@ pub unsafe extern "C" fn cosmic_run(config: *const CosmicConfig) -> i32 {
387 412
388 let size = cosmic::iced::Size::new(413 let size = cosmic::iced::Size::new(
389 if c.width == 0 { 420.0 } else { c.width as f32 },414 if c.width == 0 { 420.0 } else { c.width as f32 },
390- if c.height == 0 { 260.0 } else { c.height as f32 },415+ if c.height == 0 {
416+ 260.0
417+ } else {
418+ c.height as f32
419+ },
391 );420 );
392 let settings = cosmic::app::Settings::default().size(size).debug(false);421 let settings = cosmic::app::Settings::default().size(size).debug(false);
393 422