Add initial element inspector for Zed development (#31315)

Open inspector with `dev: toggle inspector` from command palette or
`cmd-alt-i` on mac or `ctrl-alt-i` on linux.

https://github.com/user-attachments/assets/54c43034-d40b-414e-ba9b-190bed2e6d2f

* Picking of elements via the mouse, with scroll wheel to inspect
occluded elements.

* Temporary manipulation of the selected element.

* Layout info and JSON-based style manipulation for `Div`.

* Navigation to code that constructed the element.

Big thanks to @as-cii and @maxdeviant for sorting out how to implement
the core of an inspector.

Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Marshall Bowers <git@maxdeviant.com>
Co-authored-by: Federico Dionisi <code@fdionisi.me>
This commit is contained in:
Michael Sloan 2025-05-23 17:08:59 -06:00 committed by GitHub
parent 685933b5c8
commit ab59982bf7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
74 changed files with 2631 additions and 406 deletions

View file

@ -133,21 +133,18 @@ impl LineWrapper {
&mut self,
line: SharedString,
truncate_width: Pixels,
ellipsis: Option<&str>,
truncation_suffix: &str,
runs: &mut Vec<TextRun>,
) -> SharedString {
let mut width = px(0.);
let mut ellipsis_width = px(0.);
if let Some(ellipsis) = ellipsis {
for c in ellipsis.chars() {
ellipsis_width += self.width_for_char(c);
}
}
let mut suffix_width = truncation_suffix
.chars()
.map(|c| self.width_for_char(c))
.fold(px(0.0), |a, x| a + x);
let mut char_indices = line.char_indices();
let mut truncate_ix = 0;
for (ix, c) in char_indices {
if width + ellipsis_width < truncate_width {
if width + suffix_width < truncate_width {
truncate_ix = ix;
}
@ -155,9 +152,9 @@ impl LineWrapper {
width += char_width;
if width.floor() > truncate_width {
let ellipsis = ellipsis.unwrap_or("");
let result = SharedString::from(format!("{}{}", &line[..truncate_ix], ellipsis));
update_runs_after_truncation(&result, ellipsis, runs);
let result =
SharedString::from(format!("{}{}", &line[..truncate_ix], truncation_suffix));
update_runs_after_truncation(&result, truncation_suffix, runs);
return result;
}
@ -500,7 +497,7 @@ mod tests {
wrapper: &mut LineWrapper,
text: &'static str,
result: &'static str,
ellipsis: Option<&str>,
ellipsis: &str,
) {
let dummy_run_lens = vec![text.len()];
let mut dummy_runs = generate_test_runs(&dummy_run_lens);
@ -515,19 +512,19 @@ mod tests {
&mut wrapper,
"aa bbb cccc ddddd eeee ffff gggg",
"aa bbb cccc ddddd eeee",
None,
"",
);
perform_test(
&mut wrapper,
"aa bbb cccc ddddd eeee ffff gggg",
"aa bbb cccc ddddd eee…",
Some(""),
"",
);
perform_test(
&mut wrapper,
"aa bbb cccc ddddd eeee ffff gggg",
"aa bbb cccc dddd......",
Some("......"),
"......",
);
}
@ -545,7 +542,7 @@ mod tests {
) {
let mut dummy_runs = generate_test_runs(run_lens);
assert_eq!(
wrapper.truncate_line(text.into(), line_width, Some(""), &mut dummy_runs),
wrapper.truncate_line(text.into(), line_width, "", &mut dummy_runs),
result
);
for (run, result_len) in dummy_runs.iter().zip(result_run_len) {