diff options
| author | Rose Hogenson <rosehogenson@posteo.net> | 2024-05-27 16:04:31 -0700 |
|---|---|---|
| committer | Rose Hogenson <rosehogenson@posteo.net> | 2024-05-27 16:04:31 -0700 |
| commit | 4debd88807c538aa430ce69b83fdb291f687b1b1 (patch) | |
| tree | 5def99861585367826937c2bdbbfba7f23e07f0b /src/main.rs | |
| download | qc-4debd88807c538aa430ce69b83fdb291f687b1b1.tar.zst | |
Rewrite in Rust.
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..1f4291e --- /dev/null +++ b/src/main.rs @@ -0,0 +1,89 @@ +mod lexer; +mod num; +mod parser; + +use gdk4::{Key, ModifierType}; +use gtk4::glib::{clone, ExitCode}; +use gtk4::prelude::{ + ApplicationExt, ApplicationExtManual, EditableExt, GridExt, GtkWindowExt, WidgetExt, +}; +use gtk4::{glib, Application, ApplicationWindow, Entry, EventControllerKey, Grid}; +use std::sync::{Arc, Mutex}; + +fn send_mail<T>(m: &Mutex<Option<T>>, msg: T) { + let mut guard = m.lock().unwrap(); + *guard = Some(msg); +} + +fn get_mail<T>(m: &Mutex<Option<T>>) -> Option<T> { + let mut guard = m.lock().unwrap(); + std::mem::take(&mut guard) +} + +fn main() -> ExitCode { + let app = Application::builder() + .application_id("com.github.rhogenson.qc") + .build(); + app.connect_activate(|app| { + let window = ApplicationWindow::builder() + .application(app) + .decorated(false) + .resizable(false) + .build(); + + let grid = Grid::new(); + window.set_child(Some(&grid)); + + let input = Entry::new(); + grid.attach(&input, 0, 0, 1, 1); + + let output = Entry::builder().editable(false).build(); + grid.attach(&output, 0, 1, 1, 1); + + let (ping_send, ping_recv) = std::sync::mpsc::sync_channel(1); + let mailbox = Arc::new(Mutex::new(None)); + + let key_controller = EventControllerKey::new(); + key_controller.connect_key_released( + clone!(@weak window, @weak input, @strong mailbox => move |_, k, _, modifiers| { + if k == Key::Escape + || k == Key::Return + || k == Key::bracketleft && modifiers.contains(ModifierType::CONTROL_MASK) + { + window.destroy(); + } + send_mail(mailbox.as_ref(), format!("{}", input.text())); + let _ = ping_send.try_send(()); + }), + ); + window.add_controller(key_controller); + + let (output_send, output_recv) = async_channel::bounded(1); + let (confirm_send, confirm_recv) = async_channel::bounded(1); + + gtk4::gio::spawn_blocking(move || loop { + let Ok(_) = ping_recv.recv() else { + return; + }; + let Some(input) = get_mail(mailbox.as_ref()) else { + continue; + }; + let Some(result) = parser::parse(&input) else { + continue; + }; + output_send.send_blocking(result).unwrap(); + confirm_recv.recv_blocking().unwrap(); + }); + + glib::spawn_future_local(clone!(@weak output => async move { + while let Ok(result) = output_recv.recv().await { + output.set_text(&format!("{}", result)); + confirm_send.send(()).await.unwrap(); + } + })); + + window.present(); + }); + + app.run() +} |
