logiguard fork v3: full patch set on verified 8c74db0 tree
Includes prior-session patches (carry forward so the app compiles): - crates/gpui/build.rs: cross-compile manifest fix - crates/gpui/src/platform.rs: PlatformWindow::activate_with_token trait method - crates/gpui/src/window.rs: Window::activate_with_token public API - crates/gpui_linux/src/linux/wayland/window.rs: WaylandWindow::activate_with_token + activate() keyboard-serial fix Plus the focus-serial fix: - serial.rs: SerialKind::KeyboardEnter - client.rs: store wl_keyboard.enter serial; latest_serial_of() Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
180
crates/editor_benchmarks/src/main.rs
Normal file
180
crates/editor_benchmarks/src/main.rs
Normal file
@@ -0,0 +1,180 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use editor::Editor;
|
||||
use gpui::{AppContext as _, AsyncWindowContext, WeakEntity, WindowBounds, WindowOptions};
|
||||
use language::Buffer;
|
||||
use multi_buffer::Anchor;
|
||||
use project::search::SearchQuery;
|
||||
use workspace::searchable::SearchableItem;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Args {
|
||||
file: String,
|
||||
query: String,
|
||||
replace: Option<String>,
|
||||
regex: bool,
|
||||
whole_word: bool,
|
||||
case_sensitive: bool,
|
||||
}
|
||||
|
||||
fn parse_args() -> Args {
|
||||
let mut args_iter = std::env::args().skip(1);
|
||||
let mut parsed = Args {
|
||||
file: String::new(),
|
||||
query: String::new(),
|
||||
replace: None,
|
||||
regex: false,
|
||||
whole_word: false,
|
||||
case_sensitive: false,
|
||||
};
|
||||
|
||||
let mut positional = Vec::new();
|
||||
while let Some(arg) = args_iter.next() {
|
||||
match arg.as_str() {
|
||||
"--regex" => parsed.regex = true,
|
||||
"--whole-word" => parsed.whole_word = true,
|
||||
"--case-sensitive" => parsed.case_sensitive = true,
|
||||
"-r" | "--replace" => {
|
||||
parsed.replace = args_iter.next();
|
||||
}
|
||||
"--help" | "-h" => {
|
||||
eprintln!(
|
||||
"Usage: editor_benchmarks [OPTIONS] <FILE> <QUERY>\n\n\
|
||||
Arguments:\n \
|
||||
<FILE> Path to the file to search in\n \
|
||||
<QUERY> The search query string\n\n\
|
||||
Options:\n \
|
||||
-r, --replace <TEXT> Replacement text (runs replace_all)\n \
|
||||
--regex Treat query as regex\n \
|
||||
--whole-word Match whole words only\n \
|
||||
--case-sensitive Case-sensitive matching\n \
|
||||
-h, --help Print help"
|
||||
);
|
||||
std::process::exit(0);
|
||||
}
|
||||
other => positional.push(other.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
if positional.len() < 2 {
|
||||
eprintln!("Usage: editor_benchmarks [OPTIONS] <FILE> <QUERY>");
|
||||
std::process::exit(1);
|
||||
}
|
||||
parsed.file = positional.remove(0);
|
||||
parsed.query = positional.remove(0);
|
||||
parsed
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = parse_args();
|
||||
|
||||
let file_contents = std::fs::read_to_string(&args.file).expect("failed to read input file");
|
||||
let file_len = file_contents.len();
|
||||
println!("Read {} ({file_len} bytes)", args.file);
|
||||
|
||||
let mut query = if args.regex {
|
||||
SearchQuery::regex(
|
||||
&args.query,
|
||||
args.whole_word,
|
||||
args.case_sensitive,
|
||||
false,
|
||||
false,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
false,
|
||||
None,
|
||||
)
|
||||
.expect("invalid regex query")
|
||||
} else {
|
||||
SearchQuery::text(
|
||||
&args.query,
|
||||
args.whole_word,
|
||||
args.case_sensitive,
|
||||
false,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
false,
|
||||
None,
|
||||
)
|
||||
.expect("invalid text query")
|
||||
};
|
||||
|
||||
if let Some(replacement) = args.replace.as_deref() {
|
||||
query = query.with_replacement(replacement.to_string());
|
||||
}
|
||||
|
||||
let query = Arc::new(query);
|
||||
let has_replacement = args.replace.is_some();
|
||||
|
||||
gpui_platform::headless().run(move |cx| {
|
||||
release_channel::init_test(
|
||||
semver::Version::new(0, 0, 0),
|
||||
release_channel::ReleaseChannel::Dev,
|
||||
cx,
|
||||
);
|
||||
settings::init(cx);
|
||||
theme::init(theme::LoadThemes::JustBase, cx);
|
||||
editor::init(cx);
|
||||
|
||||
let buffer = cx.new(|cx| Buffer::local(file_contents, cx));
|
||||
|
||||
let window_handle = cx
|
||||
.open_window(
|
||||
WindowOptions {
|
||||
window_bounds: Some(WindowBounds::Windowed(gpui::Bounds {
|
||||
origin: Default::default(),
|
||||
size: gpui::size(gpui::px(800.0), gpui::px(600.0)),
|
||||
})),
|
||||
focus: false,
|
||||
show: false,
|
||||
..Default::default()
|
||||
},
|
||||
|window, cx| cx.new(|cx| Editor::for_buffer(buffer, None, window, cx)),
|
||||
)
|
||||
.expect("failed to open window");
|
||||
|
||||
window_handle
|
||||
.update(cx, move |_, window, cx| {
|
||||
cx.spawn_in(
|
||||
window,
|
||||
async move |weak: WeakEntity<Editor>,
|
||||
cx: &mut AsyncWindowContext|
|
||||
-> anyhow::Result<()> {
|
||||
let find_task = weak.update_in(cx, |editor, window, cx| {
|
||||
editor.find_matches(query.clone(), window, cx)
|
||||
})?;
|
||||
|
||||
println!("Finding matches...");
|
||||
let timer = std::time::Instant::now();
|
||||
let matches: Vec<std::ops::Range<Anchor>> = find_task.await;
|
||||
let find_elapsed = timer.elapsed();
|
||||
println!("Found {} matches in {find_elapsed:?}", matches.len());
|
||||
|
||||
if has_replacement && !matches.is_empty() {
|
||||
window_handle.update(cx, |editor: &mut Editor, window, cx| {
|
||||
let mut match_iter = matches.iter();
|
||||
println!("Replacing all matches...");
|
||||
let timer = std::time::Instant::now();
|
||||
editor.replace_all(
|
||||
&mut match_iter,
|
||||
&query,
|
||||
Default::default(),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
let replace_elapsed = timer.elapsed();
|
||||
println!(
|
||||
"Replaced {} matches in {replace_elapsed:?}",
|
||||
matches.len()
|
||||
);
|
||||
})?;
|
||||
}
|
||||
|
||||
std::process::exit(0);
|
||||
},
|
||||
)
|
||||
.detach();
|
||||
})
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user