diff --git a/Cargo.toml b/Cargo.toml index 893433d..563c287 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,4 +3,12 @@ name = "glint" version = "0.1.0" edition = "2024" +[lib] +name = "glint" +path = "src/lib.rs" + +[[bin]] +name = "glint" +path = "src/main.rs" + [dependencies] diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..f1dfc4e --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,8 @@ +pub mod ast; +pub mod compiler; +pub mod opcodes; +pub mod parser; + +pub use ast::{Directive, ModuleSoA, NodeId, Value}; +pub use compiler::Compiler; +pub use parser::Parser; diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index df46b82..0000000 --- a/src/main.rs +++ /dev/null @@ -1,302 +0,0 @@ -mod ast; -mod compiler; -mod opcodes; -mod parser; - -use compiler::Compiler; -use parser::Parser; -use std::collections::HashSet; -use std::fs::File; -use std::io::Write; - -const INPUT: &str = r#" -@version 1 -@style "desktop.glts" - -@global $username = !rhei: os.env("USER") -@global $hostname = !rhei: os.hostname() -@global $locale = "ru_RU" -@global $scaleFactor = 1.0 - -@singleton Config { - wallpaper = fs:/home/$username/.config/de/wallpaper.jpg - wallpaperFit = "cover" - iconTheme = "papirus-dark" - fontMain = "Inter" - fontMono = "JetBrains Mono" - fontSize = 13 - workspaces = 4 - animEnabled = true - accentColor = #cba6f7 - taskbarPos = "bottom" -} - -@singleton SystemState { - battery = !rhei: sys.battery() - volume = !rhei: sys.volume.get() - brightness = !rhei: sys.brightness.get() - network = !rhei: sys.network.status() - timezone = !rhei: os.timezone() -} - -@component DesktopIcon(label: str, icon: fspath, exec: str) { - Button(class="desktop-icon") { - @on click { - !rhei: process.spawn($exec) - } - @on dblclick { - !rhei { - process.spawn($exec) - wm.raise(process.lastPid()) - } - } - Image(src=$icon, class="icon-img") {} - Label(class="icon-label") $label - } -} - -@component BatteryWidget { - @if $SystemState.battery.present { - @let $lvl = $SystemState.battery.level - @let $ico = !rhei: icons.battery($lvl) - - Panel(class="tray-item") { - Icon(src=$ico, class="tray-icon") {} - @if $SystemState.battery.charging { - Icon(src=fs:/usr/share/glint-de/icons/charging.svg, - class="tray-icon tray-icon--accent") {} - } - } - } -} - -@component ClockWidget { - @let $time = !rhei: sys.time.format("%H:%M", $SystemState.timezone) - @let $date = !rhei: sys.time.format("%d %b", $SystemState.timezone) - - Panel(class="clock-widget") { - @on click { - !rhei: ui.toggle("calendar-popup") - } - Label(class="clock-time") $time - Label(class="clock-date") $date - } -} - -@component SystemTray { - Panel(id="system-tray", class="tray") { - BatteryWidget {} - - @if $SystemState.network.connected { - Icon(class="tray-icon", - src=!rhei: icons.network($SystemState.network.type)) {} - } @else { - Icon(class="tray-icon tray-icon--warn", - src=fs:/usr/share/glint-de/icons/net-offline.svg) {} - } - - Slider(id="vol-slider", class="tray-slider", - value=$SystemState.volume, min=0, max=100) { - @on change { - !rhei: sys.volume.set($self.value) - } - } - - ClockWidget {} - } -} - -Screen(id="root", width=1920, height=1080, scale=$scaleFactor) { - Wallpaper(id="bg", - src=$Config.wallpaper, - fallback=fs:/usr/share/glint-de/wallpapers/default.jpg, - fit=$Config.wallpaperFit, - watch=true) {} - - Panel(id="desktop", class="desktop") { - @let $desktopFiles = !rhei: fs.glob("/home/$username/Desktop/*.desktop") - - @each $f in $desktopFiles { - @let $entry = !rhei: xdg.parseDesktop($f) - DesktopIcon( - label=$entry.name, - icon=!rhei: icons.resolve($entry.icon, $Config.iconTheme), - exec=$entry.exec - ) {} - } - - @on contextmenu { - !rhei: ui.show("desktop-ctx") - } - } - - ContextMenu(id="desktop-ctx", class="ctx-menu", visible=false) { - MenuItem(class="ctx-item") { - @on click { !rhei: ui.show("settings") } - "Настройки рабочего стола" - } - MenuItem(class="ctx-item") { - @on click { !rhei: wallpaper.showPicker() } - "Сменить обои" - } - MenuDivider {} - MenuItem(class="ctx-item ctx-item--danger") { - @on click { !rhei: session.logout() } - "Выйти из сеанса" - } - } - - Panel(id="taskbar", class="taskbar") { - Button(id="launcher-btn", class="launcher-button") { - @on click { !rhei: ui.toggle("app-launcher") } - Image(src=fs:/usr/share/glint-de/logo.svg) {} - } - - Panel(id="window-list", class="window-list") { - @let $wins = !rhei: wm.getWindows() - - @each $w in $wins { - Button(class="taskbar-win", data-wid=$w.id, - active=$w.focused) { - @on click { !rhei: wm.focus($w.id) } - @on middleclick { !rhei: wm.close($w.id) } - Icon(src=$w.icon, class="win-icon") {} - Label(class="win-title") $w.title - } - } - } - SystemTray {} - } - - Overlay(id="app-launcher", class="launcher", visible=false) { - @on keydown(key="Escape") { - !rhei: ui.hide("app-launcher") - } - - Input(id="launcher-search", class="launcher-search", - placeholder="Поиск приложений...", - autofocus=true) { - @on input { - !rhei: launcher.filter($self.value) - } - } - - Grid(id="app-grid", class="launcher-grid", columns=6) { - @let $apps = !rhei: apps.listAll() - - @each $app in $apps { - Button(class="launcher-app") { - @on click { - !rhei { - process.spawn($app.exec) - ui.hide("app-launcher") - } - } - Image(src=$app.icon, class="app-icon") {} - Label(class="app-name") $app.name - } - } - } - } - - Overlay(id="notif-layer", class="notif-layer") { - @let $notifs = !rhei: notifications.active() - - @each $n in $notifs { - Panel(class="notif-card", data-id=$n.id) { - Panel(class="notif-header") { - Icon(src=$n.appIcon, class="notif-icon") {} - Label(class="notif-app") $n.appName - Button(class="notif-close") { - @on click { !rhei: notifications.dismiss($n.id) } - "×" - } - } - Label(class="notif-title") $n.summary - @if $n.body { - Label(class="notif-body") $n.body - } - } - } - } - - @if !rhei: os.env("GLINT_DEV") { - !rhei { - debug.overlay.show() - debug.log("DE инициализирован. Пользователь: " + $username) - debug.log("Синглтоны: Config, SystemState") - } - } -} -"#; - -fn main() { - let mut parser = Parser::new(INPUT); - match parser.parse_all() { - Ok(_) => { - println!("Parse is successful"); - - let m = &parser.module; - - let mut child_indices = HashSet::new(); - for (start, len) in &m.elem_child_spans { - for i in *start..(*start + *len) { - child_indices.insert(i as usize); - } - } - for dir in &m.directives { - let span = match dir { - ast::Directive::Component { child_span, .. } => Some(child_span), - ast::Directive::If { - child_span, - else_span, - .. - } => { - if let Some(es) = else_span { - for i in es.0..(es.0 + es.1) { - child_indices.insert(i as usize); - } - } - Some(child_span) - } - ast::Directive::Each { child_span, .. } => Some(child_span), - ast::Directive::On { child_span, .. } => Some(child_span), - _ => None, - }; - if let Some((start, len)) = span { - for i in *start..(*start + *len) { - child_indices.insert(i as usize); - } - } - } - - let mut root_nodes = Vec::new(); - for (i, node) in m.hierarchy.iter().enumerate() { - if !child_indices.contains(&i) { - root_nodes.push(node.clone()); - } - } - - println!("Compile..."); - let compiler = Compiler::new(m); - let bytecode = compiler.compile(&root_nodes); - - let output_path = "desktop.glbc"; - let mut file = File::create(output_path).expect("Не удалось создать файл"); - file.write_all(&bytecode) - .expect("Не удалось записать байткод"); - - println!( - "Compile is successful. Compiled in {} ({} bytes)", - output_path, - bytecode.len() - ); - } - Err(e) => { - eprintln!("❌ Error of parse: {}", e); - } - } -} - -#[cfg(test)] -mod tests;