Skip to repository content183 lines · 6.4 KB · rust
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T03:36:22.016Z Public web read
NIP-34 coordinate
30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omegaMaintainersHidden in public view
References2 branches · 1 tag
Read-only clone
git clone https://openagents.com/git/tenant.openagents/omega.gitBrowse files
main.rs
1use std::sync::Arc;
2
3use editor::Editor;
4use gpui::{AppContext as _, AsyncWindowContext, WeakEntity, WindowBounds, WindowOptions};
5use language::Buffer;
6use multi_buffer::Anchor;
7use project::search::SearchQuery;
8use workspace::searchable::SearchableItem;
9
10#[derive(Debug)]
11struct Args {
12 file: String,
13 query: String,
14 replace: Option<String>,
15 regex: bool,
16 whole_word: bool,
17 case_sensitive: bool,
18 single: bool,
19}
20
21fn parse_args() -> Args {
22 let mut args_iter = std::env::args().skip(1);
23 let mut parsed = Args {
24 file: String::new(),
25 query: String::new(),
26 replace: None,
27 regex: false,
28 whole_word: false,
29 case_sensitive: false,
30 single: false,
31 };
32
33 let mut positional = Vec::new();
34 while let Some(arg) = args_iter.next() {
35 match arg.as_str() {
36 "--regex" => parsed.regex = true,
37 "--whole-word" => parsed.whole_word = true,
38 "--case-sensitive" => parsed.case_sensitive = true,
39 "--single" => parsed.single = true,
40 "-r" | "--replace" => {
41 parsed.replace = args_iter.next();
42 }
43 "--help" | "-h" => {
44 eprintln!(
45 "Usage: editor_benchmarks [OPTIONS] <FILE> <QUERY>\n\n\
46 Arguments:\n \
47 <FILE> Path to the file to search in\n \
48 <QUERY> The search query string\n\n\
49 Options:\n \
50 -r, --replace <TEXT> Replacement text (runs replace_all)\n \
51 --regex Treat query as regex\n \
52 --whole-word Match whole words only\n \
53 --case-sensitive Case-sensitive matching\n \
54 -h, --help Print help"
55 );
56 std::process::exit(0);
57 }
58 other => positional.push(other.to_string()),
59 }
60 }
61
62 if positional.len() < 2 {
63 eprintln!("Usage: editor_benchmarks [OPTIONS] <FILE> <QUERY>");
64 std::process::exit(1);
65 }
66 parsed.file = positional.remove(0);
67 parsed.query = positional.remove(0);
68 parsed
69}
70
71fn main() {
72 let args = parse_args();
73
74 let file_contents = std::fs::read_to_string(&args.file).expect("failed to read input file");
75 let file_len = file_contents.len();
76 println!("Read {} ({file_len} bytes)", args.file);
77
78 let mut query = if args.regex {
79 SearchQuery::regex(
80 &args.query,
81 args.whole_word,
82 args.case_sensitive,
83 false,
84 false,
85 Default::default(),
86 Default::default(),
87 false,
88 None,
89 )
90 .expect("invalid regex query")
91 } else {
92 SearchQuery::text(
93 &args.query,
94 args.whole_word,
95 args.case_sensitive,
96 false,
97 Default::default(),
98 Default::default(),
99 false,
100 None,
101 )
102 .expect("invalid text query")
103 };
104
105 if let Some(replacement) = args.replace.as_deref() {
106 query = query.with_replacement(replacement.to_string());
107 }
108
109 let query = Arc::new(query);
110 let has_replacement = args.replace.is_some();
111 let single = args.single;
112
113 gpui_platform::headless().run(move |cx| {
114 release_channel::init_test(
115 semver::Version::new(0, 0, 0),
116 release_channel::ReleaseChannel::Dev,
117 cx,
118 );
119 settings::init(cx);
120 theme::init(theme::LoadThemes::JustBase, cx);
121 editor::init(cx);
122
123 let buffer = cx.new(|cx| Buffer::local(file_contents, cx));
124
125 let window_handle = cx
126 .open_window(
127 WindowOptions {
128 window_bounds: Some(WindowBounds::Windowed(gpui::Bounds {
129 origin: Default::default(),
130 size: gpui::size(gpui::px(800.0), gpui::px(600.0)),
131 })),
132 focus: false,
133 show: false,
134 ..Default::default()
135 },
136 |window, cx| cx.new(|cx| Editor::for_buffer(buffer, None, window, cx)),
137 )
138 .expect("failed to open window");
139
140 window_handle
141 .update(cx, move |_, window, cx| {
142 cx.spawn_in(
143 window,
144 async move |weak: WeakEntity<Editor>,
145 cx: &mut AsyncWindowContext|
146 -> anyhow::Result<()> {
147 let find_task = weak.update_in(cx, |editor, window, cx| {
148 editor.find_matches(query.clone(), window, cx)
149 })?;
150
151 println!("Finding matches...");
152 let timer = std::time::Instant::now();
153 let matches: Vec<std::ops::Range<Anchor>> = find_task.await;
154 let find_elapsed = timer.elapsed();
155 println!("Found {} matches in {find_elapsed:?}", matches.len());
156
157 if has_replacement && !matches.is_empty() {
158 window_handle.update(cx, |editor: &mut Editor, window, cx| {
159 let to_replace = if single { 1 } else { matches.len() };
160 let mut match_iter = matches.iter().take(to_replace);
161 println!("Replacing {to_replace} matches...");
162 let timer = std::time::Instant::now();
163 editor.replace_all(
164 &mut match_iter,
165 &query,
166 Default::default(),
167 window,
168 cx,
169 );
170 let replace_elapsed = timer.elapsed();
171 println!("Replaced {to_replace} matches in {replace_elapsed:?}");
172 })?;
173 }
174
175 std::process::exit(0);
176 },
177 )
178 .detach();
179 })
180 .unwrap();
181 });
182}
183