1#![allow(non_camel_case_types)]
2#![allow(non_snake_case)]
3#![allow(non_upper_case_globals)]
4#![allow(clippy::all)]
5#![allow(rustdoc::all)]
6
7mod bindings;
8
9use std::ops::Deref;
10
11pub use bindings::*;
12
13#[macro_export]
15macro_rules! sized {
16 ($ty:ty) => {{
17 let mut t = <$ty as ::std::default::Default>::default();
18 t.size = ::std::mem::size_of::<$ty>();
19 t
20 }};
21}
22
23impl<S> From<S> for GhosttyString
24where
25 S: Deref<Target = str>,
26{
27 fn from(value: S) -> Self {
28 Self {
29 ptr: value.as_ptr(),
30 len: value.len(),
31 }
32 }
33}
34
35impl GhosttyString {
36 pub unsafe fn to_str<'a>(self) -> &'a str {
42 let slice = unsafe { std::slice::from_raw_parts(self.ptr, self.len) };
44 unsafe { std::str::from_utf8_unchecked(slice) }
45 }
46}
47
48pub const EXPORTED_API_SYMBOLS: &[&str] = &[
50 "ghostty_build_info",
51 "ghostty_cell_get",
52 "ghostty_color_rgb_get",
53 "ghostty_focus_encode",
54 "ghostty_formatter_format_alloc",
55 "ghostty_formatter_format_buf",
56 "ghostty_formatter_free",
57 "ghostty_formatter_terminal_new",
58 "ghostty_grid_ref_cell",
59 "ghostty_grid_ref_graphemes",
60 "ghostty_grid_ref_row",
61 "ghostty_grid_ref_style",
62 "ghostty_key_encoder_encode",
63 "ghostty_key_encoder_free",
64 "ghostty_key_encoder_new",
65 "ghostty_key_encoder_setopt",
66 "ghostty_key_encoder_setopt_from_terminal",
67 "ghostty_key_event_free",
68 "ghostty_key_event_get_action",
69 "ghostty_key_event_get_composing",
70 "ghostty_key_event_get_consumed_mods",
71 "ghostty_key_event_get_key",
72 "ghostty_key_event_get_mods",
73 "ghostty_key_event_get_unshifted_codepoint",
74 "ghostty_key_event_get_utf8",
75 "ghostty_key_event_new",
76 "ghostty_key_event_set_action",
77 "ghostty_key_event_set_composing",
78 "ghostty_key_event_set_consumed_mods",
79 "ghostty_key_event_set_key",
80 "ghostty_key_event_set_mods",
81 "ghostty_key_event_set_unshifted_codepoint",
82 "ghostty_key_event_set_utf8",
83 "ghostty_mode_report_encode",
84 "ghostty_mouse_encoder_encode",
85 "ghostty_mouse_encoder_free",
86 "ghostty_mouse_encoder_new",
87 "ghostty_mouse_encoder_reset",
88 "ghostty_mouse_encoder_setopt",
89 "ghostty_mouse_encoder_setopt_from_terminal",
90 "ghostty_mouse_event_clear_button",
91 "ghostty_mouse_event_free",
92 "ghostty_mouse_event_get_action",
93 "ghostty_mouse_event_get_button",
94 "ghostty_mouse_event_get_mods",
95 "ghostty_mouse_event_get_position",
96 "ghostty_mouse_event_new",
97 "ghostty_mouse_event_set_action",
98 "ghostty_mouse_event_set_button",
99 "ghostty_mouse_event_set_mods",
100 "ghostty_mouse_event_set_position",
101 "ghostty_osc_command_data",
102 "ghostty_osc_command_type",
103 "ghostty_osc_end",
104 "ghostty_osc_free",
105 "ghostty_osc_new",
106 "ghostty_osc_next",
107 "ghostty_osc_reset",
108 "ghostty_paste_is_safe",
109 "ghostty_render_state_colors_get",
110 "ghostty_render_state_free",
111 "ghostty_render_state_get",
112 "ghostty_render_state_new",
113 "ghostty_render_state_row_cells_free",
114 "ghostty_render_state_row_cells_get",
115 "ghostty_render_state_row_cells_new",
116 "ghostty_render_state_row_cells_next",
117 "ghostty_render_state_row_cells_select",
118 "ghostty_render_state_row_get",
119 "ghostty_render_state_row_iterator_free",
120 "ghostty_render_state_row_iterator_new",
121 "ghostty_render_state_row_iterator_next",
122 "ghostty_render_state_row_set",
123 "ghostty_render_state_set",
124 "ghostty_render_state_update",
125 "ghostty_row_get",
126 "ghostty_sgr_attribute_tag",
127 "ghostty_sgr_attribute_value",
128 "ghostty_sgr_free",
129 "ghostty_sgr_new",
130 "ghostty_sgr_next",
131 "ghostty_sgr_reset",
132 "ghostty_sgr_set_params",
133 "ghostty_sgr_unknown_full",
134 "ghostty_sgr_unknown_partial",
135 "ghostty_size_report_encode",
136 "ghostty_style_default",
137 "ghostty_style_is_default",
138 "ghostty_terminal_free",
139 "ghostty_terminal_get",
140 "ghostty_terminal_grid_ref",
141 "ghostty_terminal_mode_get",
142 "ghostty_terminal_mode_set",
143 "ghostty_terminal_new",
144 "ghostty_terminal_reset",
145 "ghostty_terminal_resize",
146 "ghostty_terminal_scroll_viewport",
147 "ghostty_terminal_vt_write",
148];
149
150#[cfg(test)]
151mod tests {
152 use std::collections::BTreeSet;
153
154 use super::EXPORTED_API_SYMBOLS;
155
156 fn parse_binding_symbols(input: &str) -> BTreeSet<String> {
157 input
158 .lines()
159 .filter_map(|line| {
160 let line = line.trim();
161 if !line.starts_with("pub fn ghostty_") {
162 return None;
163 }
164
165 let start = "pub fn ".len();
166 let rest = &line[start..];
167 let end = rest.find('(')?;
168 Some(rest[..end].to_owned())
169 })
170 .collect()
171 }
172
173 fn parse_header_symbols(input: &str) -> BTreeSet<String> {
174 let mut symbols = BTreeSet::new();
175 let mut statement = String::new();
176
177 for line in input.lines() {
178 let trimmed = line.trim();
179
180 if trimmed.starts_with('#') || trimmed.starts_with("//") || trimmed.is_empty() {
181 continue;
182 }
183
184 if trimmed.starts_with("static") {
186 continue;
187 }
188
189 if !statement.is_empty() {
190 statement.push(' ');
191 }
192 statement.push_str(trimmed);
193
194 if !trimmed.ends_with(';') && !trimmed.ends_with('{') {
195 continue;
196 }
197
198 if let Some(end) = statement.find('(') {
199 let before_paren = &statement[..end];
200 if let Some(candidate) = before_paren.split_whitespace().last() {
201 let candidate = candidate.trim_start_matches('*');
203 if candidate.starts_with("ghostty_")
204 && candidate
205 .chars()
206 .all(|char| char.is_ascii_alphanumeric() || char == '_')
207 {
208 symbols.insert(candidate.to_owned());
209 }
210 }
211 }
212
213 statement.clear();
214 }
215
216 symbols
217 }
218
219 #[test]
220 fn exported_manifest_matches_bindings() {
221 let from_bindings = parse_binding_symbols(include_str!("bindings.rs"));
222 let from_manifest: BTreeSet<String> = EXPORTED_API_SYMBOLS
223 .iter()
224 .map(|symbol| (*symbol).to_owned())
225 .collect();
226 assert_eq!(from_manifest, from_bindings);
227 }
228
229 #[test]
230 fn exported_manifest_is_sorted_and_unique() {
231 let mut prev = "";
232 for symbol in EXPORTED_API_SYMBOLS {
233 assert!(
234 *symbol > prev,
235 "EXPORTED_API_SYMBOLS is not sorted or has duplicates: {prev:?} >= {symbol:?}"
236 );
237 prev = symbol;
238 }
239 }
240}