rust: app crate scaffolding, terminal colour schemes

This commit is contained in:
Andy Dixon
2026-10-11 16:18:15 +01:00
parent 25e5f67a4d
commit 4674c7cb3f
5 changed files with 2898 additions and 19 deletions
+1
View File
@@ -75,3 +75,4 @@ build/releases/manifest*
# Rust port compatibility fixtures (generated by cmd/genfixtures)
!rust/core/tests/fixtures/**
.claude/worktrees/
+2736 -19
View File
File diff suppressed because it is too large Load Diff
+17
View File
@@ -2,6 +2,23 @@
name = "nexus"
version.workspace = true
edition.workspace = true
build = "build.rs"
[[bin]]
name = "nexus-terminal"
path = "src/main.rs"
[dependencies]
nexus-core = { path = "../core" }
eframe = { version = "0.36", default-features = false, features = ["default_fonts", "glow", "wayland", "x11", "accesskit", "persistence"] }
egui = "0.36"
egui-phosphor = "0.14"
rfd = "0.17"
image = { version = "0.25", default-features = false, features = ["png"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
regex = "1"
alacritty_terminal = "0.26.0"
[build-dependencies]
winresource = "0.1"
+14
View File
@@ -0,0 +1,14 @@
//! Embeds the icon and version info into the Windows executable.
fn main() {
println!("cargo:rerun-if-changed=../packaging/windows/nexus.ico");
if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("windows") {
let mut res = winresource::WindowsResource::new();
if std::path::Path::new("../packaging/windows/nexus.ico").exists() {
res.set_icon("../packaging/windows/nexus.ico");
}
res.set("ProductName", "Nexus Terminal").set("FileDescription", "Nexus Terminal");
if let Err(e) = res.compile() {
println!("cargo:warning=Windows icon not embedded: {e}");
}
}
}
+130
View File
@@ -0,0 +1,130 @@
//! The 11 terminal colour schemes, generated from the web build's themes.js.
pub struct TermTheme {
pub id: &'static str,
pub label: &'static str,
pub background: [u8; 4],
pub foreground: [u8; 4],
pub cursor: [u8; 4],
pub cursor_accent: [u8; 4],
pub selection: [u8; 4],
/// black, red, green, yellow, blue, magenta, cyan, white, then the bright eight.
pub ansi: [[u8; 4]; 16],
}
pub const THEMES: &[TermTheme] = &[
TermTheme {
id: "charcoal",
label: "Charcoal (Default)",
background: [28, 28, 28, 255],
foreground: [228, 228, 228, 255],
cursor: [78, 205, 196, 255],
cursor_accent: [28, 28, 28, 255],
selection: [78, 205, 196, 76],
ansi: [[28, 28, 28, 255], [239, 83, 80, 255], [102, 187, 106, 255], [255, 167, 38, 255], [66, 165, 245, 255], [171, 71, 188, 255], [78, 205, 196, 255], [228, 228, 228, 255], [85, 85, 85, 255], [255, 112, 67, 255], [129, 199, 132, 255], [255, 204, 2, 255], [100, 181, 246, 255], [206, 147, 216, 255], [128, 222, 234, 255], [255, 255, 255, 255]],
},
TermTheme {
id: "solarized-dark",
label: "Solarized Dark",
background: [0, 43, 54, 255],
foreground: [131, 148, 150, 255],
cursor: [147, 161, 161, 255],
cursor_accent: [0, 43, 54, 255],
selection: [147, 161, 161, 76],
ansi: [[7, 54, 66, 255], [220, 50, 47, 255], [133, 153, 0, 255], [181, 137, 0, 255], [38, 139, 210, 255], [211, 54, 130, 255], [42, 161, 152, 255], [238, 232, 213, 255], [88, 110, 117, 255], [203, 75, 22, 255], [88, 110, 117, 255], [101, 123, 131, 255], [131, 148, 150, 255], [108, 113, 196, 255], [147, 161, 161, 255], [253, 246, 227, 255]],
},
TermTheme {
id: "monokai",
label: "Monokai",
background: [39, 40, 34, 255],
foreground: [248, 248, 242, 255],
cursor: [248, 248, 240, 255],
cursor_accent: [39, 40, 34, 255],
selection: [73, 72, 62, 153],
ansi: [[39, 40, 34, 255], [249, 38, 114, 255], [166, 226, 46, 255], [244, 191, 117, 255], [102, 217, 239, 255], [174, 129, 255, 255], [161, 239, 228, 255], [248, 248, 242, 255], [117, 113, 94, 255], [249, 38, 114, 255], [166, 226, 46, 255], [244, 191, 117, 255], [102, 217, 239, 255], [174, 129, 255, 255], [161, 239, 228, 255], [249, 248, 245, 255]],
},
TermTheme {
id: "nord",
label: "Nord",
background: [46, 52, 64, 255],
foreground: [216, 222, 233, 255],
cursor: [216, 222, 233, 255],
cursor_accent: [46, 52, 64, 255],
selection: [136, 192, 208, 76],
ansi: [[59, 66, 82, 255], [191, 97, 106, 255], [163, 190, 140, 255], [235, 203, 139, 255], [129, 161, 193, 255], [180, 142, 173, 255], [136, 192, 208, 255], [229, 233, 240, 255], [76, 86, 106, 255], [191, 97, 106, 255], [163, 190, 140, 255], [235, 203, 139, 255], [129, 161, 193, 255], [180, 142, 173, 255], [143, 188, 187, 255], [236, 239, 244, 255]],
},
TermTheme {
id: "dracula",
label: "Dracula",
background: [40, 42, 54, 255],
foreground: [248, 248, 242, 255],
cursor: [248, 248, 242, 255],
cursor_accent: [40, 42, 54, 255],
selection: [68, 71, 90, 153],
ansi: [[33, 34, 44, 255], [255, 85, 85, 255], [80, 250, 123, 255], [241, 250, 140, 255], [189, 147, 249, 255], [255, 121, 198, 255], [139, 233, 253, 255], [248, 248, 242, 255], [98, 114, 164, 255], [255, 110, 110, 255], [105, 255, 148, 255], [255, 255, 165, 255], [214, 172, 255, 255], [255, 146, 223, 255], [164, 255, 255, 255], [255, 255, 255, 255]],
},
TermTheme {
id: "one-dark",
label: "One Dark",
background: [40, 44, 52, 255],
foreground: [171, 178, 191, 255],
cursor: [82, 139, 255, 255],
cursor_accent: [40, 44, 52, 255],
selection: [82, 139, 255, 76],
ansi: [[40, 44, 52, 255], [224, 108, 117, 255], [152, 195, 121, 255], [229, 192, 123, 255], [97, 175, 239, 255], [198, 120, 221, 255], [86, 182, 194, 255], [171, 178, 191, 255], [92, 99, 112, 255], [224, 108, 117, 255], [152, 195, 121, 255], [229, 192, 123, 255], [97, 175, 239, 255], [198, 120, 221, 255], [86, 182, 194, 255], [255, 255, 255, 255]],
},
TermTheme {
id: "gruvbox-dark",
label: "Gruvbox Dark",
background: [40, 40, 40, 255],
foreground: [235, 219, 178, 255],
cursor: [235, 219, 178, 255],
cursor_accent: [40, 40, 40, 255],
selection: [214, 93, 14, 76],
ansi: [[40, 40, 40, 255], [204, 36, 29, 255], [152, 151, 26, 255], [215, 153, 33, 255], [69, 133, 136, 255], [177, 98, 134, 255], [104, 157, 106, 255], [168, 153, 132, 255], [146, 131, 116, 255], [251, 73, 52, 255], [184, 187, 38, 255], [250, 189, 47, 255], [131, 165, 152, 255], [211, 134, 155, 255], [142, 192, 124, 255], [235, 219, 178, 255]],
},
TermTheme {
id: "tokyo-night",
label: "Tokyo Night",
background: [26, 27, 38, 255],
foreground: [169, 177, 214, 255],
cursor: [192, 202, 245, 255],
cursor_accent: [26, 27, 38, 255],
selection: [41, 46, 66, 230],
ansi: [[21, 22, 30, 255], [247, 118, 142, 255], [158, 206, 106, 255], [224, 175, 104, 255], [122, 162, 247, 255], [187, 154, 247, 255], [125, 207, 255, 255], [169, 177, 214, 255], [65, 72, 104, 255], [247, 118, 142, 255], [158, 206, 106, 255], [224, 175, 104, 255], [122, 162, 247, 255], [187, 154, 247, 255], [125, 207, 255, 255], [192, 202, 245, 255]],
},
TermTheme {
id: "catppuccin-mocha",
label: "Catppuccin Mocha",
background: [30, 30, 46, 255],
foreground: [205, 214, 244, 255],
cursor: [245, 224, 220, 255],
cursor_accent: [30, 30, 46, 255],
selection: [88, 91, 112, 128],
ansi: [[69, 71, 90, 255], [243, 139, 168, 255], [166, 227, 161, 255], [249, 226, 175, 255], [137, 180, 250, 255], [245, 194, 231, 255], [148, 226, 213, 255], [186, 194, 222, 255], [88, 91, 112, 255], [243, 139, 168, 255], [166, 227, 161, 255], [249, 226, 175, 255], [137, 180, 250, 255], [245, 194, 231, 255], [148, 226, 213, 255], [166, 173, 200, 255]],
},
TermTheme {
id: "rose-pine",
label: "Rosé Pine",
background: [25, 23, 36, 255],
foreground: [224, 222, 244, 255],
cursor: [82, 79, 103, 255],
cursor_accent: [224, 222, 244, 255],
selection: [110, 106, 134, 102],
ansi: [[38, 35, 58, 255], [235, 111, 146, 255], [49, 116, 143, 255], [246, 193, 119, 255], [156, 207, 216, 255], [196, 167, 231, 255], [235, 188, 186, 255], [224, 222, 244, 255], [110, 106, 134, 255], [235, 111, 146, 255], [49, 116, 143, 255], [246, 193, 119, 255], [156, 207, 216, 255], [196, 167, 231, 255], [235, 188, 186, 255], [224, 222, 244, 255]],
},
TermTheme {
id: "solarized-light",
label: "Solarized Light",
background: [253, 246, 227, 255],
foreground: [101, 123, 131, 255],
cursor: [88, 110, 117, 255],
cursor_accent: [253, 246, 227, 255],
selection: [7, 54, 66, 51],
ansi: [[7, 54, 66, 255], [220, 50, 47, 255], [133, 153, 0, 255], [181, 137, 0, 255], [38, 139, 210, 255], [211, 54, 130, 255], [42, 161, 152, 255], [238, 232, 213, 255], [0, 43, 54, 255], [203, 75, 22, 255], [88, 110, 117, 255], [101, 123, 131, 255], [131, 148, 150, 255], [108, 113, 196, 255], [147, 161, 161, 255], [253, 246, 227, 255]],
},
];
pub fn get(id: &str) -> &'static TermTheme {
THEMES.iter().find(|t| t.id == id).unwrap_or(&THEMES[0])
}