add flake.nix

This commit is contained in:
lia
2025-09-14 12:16:34 +02:00
parent 48f1b29083
commit 6ee8b07d06
5 changed files with 315 additions and 164 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
target/
.idea/
Cargo.lock
flake.lock

113
flake.lock generated Normal file
View File

@@ -0,0 +1,113 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gitignore": {
"flake": false,
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1757487488,
"narHash": "sha256-zwE/e7CuPJUWKdvvTCB7iunV4E/+G0lKfv4kk/5Izdg=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "ab0f3607a6c7486ea22229b92ed2d355f1482ee0",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1744536153,
"narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"gitignore": "gitignore",
"nixpkgs": "nixpkgs",
"rustup": "rustup"
}
},
"rustup": {
"inputs": {
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1757730403,
"narHash": "sha256-Jxl4OZRVsXs8JxEHUVQn3oPu6zcqFyGGKaFrlNgbzp0=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "3232f7f8bd07849fc6f4ae77fe695e0abb2eba2c",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

38
flake.nix Normal file
View File

@@ -0,0 +1,38 @@
{
description = "cutie flake ~";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
gitignore = { url = "github:hercules-ci/gitignore.nix"; flake = false; };
flake-utils.url = "github:numtide/flake-utils";
rustup.url = "github:oxalica/rust-overlay";
};
outputs = inputs@{ self, nixpkgs, flake-utils, rustup, ... }:
flake-utils.lib.eachSystem [ "x86_64-linux" ] (system: let
overlays = [ (import rustup) ];
pkgs = import nixpkgs { inherit system overlays; };
libPath = with pkgs; lib.makeLibraryPath [
libGL libxkbcommon
wayland wayland-utils
musl musl-fts musl-obstack
makeWrapper pkg-config gcc
libiconv libtool autoconf automake
];
gitignoreSrc = pkgs.callPackage inputs.gitignore { };
in rec {
packages.hello = pkgs.callPackage ./default.nix { inherit gitignoreSrc; };
legacyPackages = packages;
defaultPackage = packages.hello;
devShell = pkgs.mkShell {
CARGO_INSTALL_ROOT = "${toString ./.}/.cargo";
RUST_SRC_PATH = "${pkgs.rustPlatform.rustLibSrc}";
LD_LIBRARY_PATH = libPath;
buildInputs = with pkgs; [ (rust-bin.selectLatestNightlyWith (toolchain: toolchain.complete.override {
targets = [ "x86_64-unknown-linux-musl" "wasm32-unknown-unknown" ];
})) ];
};
});
}

View File

@@ -8,165 +8,165 @@ use std::fs;
#[derive(serde::Deserialize, serde::Serialize)]
#[serde(default)]
pub struct CatnipApp {
label: String,
#[serde(skip)]
editor_theme: ColorTheme,
#[serde(skip)]
editor_syntax: Syntax,
editor_text: String,
#[serde(skip)]
value: f32,
label: String,
#[serde(skip)]
editor_theme: ColorTheme,
#[serde(skip)]
editor_syntax: Syntax,
editor_text: String,
#[serde(skip)]
value: f32,
}
impl Default for CatnipApp {
fn default() -> Self {
Self {
label: "println!(\"meow\");".to_owned(),
editor_theme: ColorTheme::default(),
editor_syntax: Syntax::default(),
editor_text: "".to_owned(),
value: 2.7,
}
fn default() -> Self {
Self {
label: "println!(\"meow\");".to_owned(),
editor_theme: ColorTheme::default(),
editor_syntax: Syntax::default(),
editor_text: "".to_owned(),
value: 2.7,
}
}
}
impl CatnipApp {
pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
if let Some(storage) = cc.storage {
return eframe::get_value(storage, eframe::APP_KEY).unwrap_or_default();
}
Default::default()
pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
if let Some(storage) = cc.storage {
return eframe::get_value(storage, eframe::APP_KEY).unwrap_or_default();
}
Default::default()
}
}
impl eframe::App for CatnipApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
let modal = Modal::new(ctx, "open folder modal :3");
modal.show(|ui| {
modal.title(ui, "Hello world!");
modal.frame(ui, |ui| {
modal.body(ui, "This is a modal.");
});
modal.buttons(ui, |ui| {
if modal.button(ui, "meow").clicked() {};
if modal.button(ui, "close").clicked() {};
});
});
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
let modal = Modal::new(ctx, "open folder modal :3");
modal.show(|ui| {
modal.title(ui, "Hello world!");
modal.frame(ui, |ui| {
modal.body(ui, "This is a modal.");
});
modal.buttons(ui, |ui| {
if modal.button(ui, "meow").clicked() {};
if modal.button(ui, "close").clicked() {};
});
});
// top bar
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
egui::menu::bar(ui, |ui| {
ui.menu_button("File", |ui| {
ui.menu_button("New …", |_| {});
ui.menu_button("Open …", |ui| {
if ui.button("File").clicked()
&& let Some(path) = rfd::FileDialog::new().pick_file()
{
self.editor_text =
fs::read_to_string(path.display().to_string()).unwrap();
ui.close_kind(UiKind::Menu)
}
if ui.button("Folder").clicked() && !modal.is_open() {
modal.open();
ui.close_kind(UiKind::Menu)
}
});
if ui.button("Quit").clicked() {
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
}
// top bar
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
egui::menu::bar(ui, |ui| {
ui.menu_button("File", |ui| {
ui.menu_button("New …", |_| {});
ui.menu_button("Open …", |ui| {
if ui.button("File").clicked()
&& let Some(path) = rfd::FileDialog::new().pick_file()
{
self.editor_text =
fs::read_to_string(path.display().to_string()).unwrap();
ui.close_kind(UiKind::Menu)
}
if ui.button("Folder").clicked() && !modal.is_open() {
modal.open();
ui.close_kind(UiKind::Menu)
}
});
if ui.button("Quit").clicked() {
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
}
});
});
});
// main content
egui::CentralPanel::default().show(ctx, |ui| {
ui.with_layout(egui::Layout::left_to_right(Align::Max), |ui| {
CodeEditor::default()
.id_source("cat editor :3")
.with_fontsize(12.0)
.with_theme(self.editor_theme)
.with_syntax(self.editor_syntax.clone())
.with_numlines(true)
.vscroll(true)
.stick_to_bottom(true)
.show(ui, &mut self.editor_text);
});
// header example:
// ui.heading("eframe template");
/* config examples with serde:
ui.horizontal(|ui| {
ui.label("Write something: ");
ui.te xt_edit_singleline(&mut self.label);
});
ui.add(egui::Slider::new(&mut self.value, 0.0..=10.0).text("value"));
*/
});
// bottom bar
egui::TopBottomPanel::bottom("bottom_panel").show(ctx, |ui| {
ui.horizontal(|ui| {
ui.spacing_mut().item_spacing.x = 0.0;
ui.label("made by ");
ui.hyperlink_to("lunarydess", "https://github.com/lunarydess");
ui.label(" with ♡");
ui.with_layout(egui::Layout::right_to_left(Align::Center), |ui| {
ui.menu_image_button(egui::include_image!("cogwheel.svg"), |ui| {
// syntax selector
egui::ComboBox::from_label("Syntax")
.wrap_mode(TextWrapMode::Wrap)
.selected_text(format!("{:?}", &self.editor_syntax.language))
.show_ui(ui, |ui| {
[
Syntax::asm(),
Syntax::shell(),
Syntax::sql(),
Syntax::lua(),
Syntax::rust(),
Syntax::python(),
Syntax::java(),
]
.iter()
.for_each(|syntax| {
ui.selectable_value(
&mut self.editor_syntax,
syntax.clone(),
syntax.language,
);
});
});
// theme selector
let mut theme = ui.ctx().options(|opt| opt.theme_preference);
egui::ComboBox::from_label("Theme")
.wrap_mode(TextWrapMode::Wrap)
.selected_text(format!("{:?}", theme))
.show_ui(ui, |ui| {
ui.selectable_value(&mut theme, ThemePreference::System, "💻 System");
ui.selectable_value(&mut theme, ThemePreference::Light, "☀ Light");
ui.selectable_value(&mut theme, ThemePreference::Dark, "🌙 Dark");
});
ui.ctx().set_theme(theme);
// scheme selector
egui::ComboBox::from_label("Scheme")
.wrap_mode(TextWrapMode::Wrap)
.selected_text(format!("{:?}", &self.editor_theme.name))
.show_ui(ui, |ui| {
DEFAULT_THEMES.iter().clone().for_each(|theme| {
ui.selectable_value(&mut self.editor_theme, *theme, theme.name);
});
});
});
});
});
});
});
}
// main content
egui::CentralPanel::default().show(ctx, |ui| {
ui.with_layout(egui::Layout::left_to_right(Align::Max), |ui| {
CodeEditor::default()
.id_source("cat editor :3")
.with_fontsize(12.0)
.with_theme(self.editor_theme)
.with_syntax(self.editor_syntax.clone())
.with_numlines(true)
.vscroll(true)
.stick_to_bottom(true)
.show(ui, &mut self.editor_text);
});
// header example:
// ui.heading("eframe template");
/* config examples with serde:
ui.horizontal(|ui| {
ui.label("Write something: ");
ui.te xt_edit_singleline(&mut self.label);
});
ui.add(egui::Slider::new(&mut self.value, 0.0..=10.0).text("value"));
*/
});
// bottom bar
egui::TopBottomPanel::bottom("bottom_panel").show(ctx, |ui| {
ui.horizontal(|ui| {
ui.spacing_mut().item_spacing.x = 0.0;
ui.label("made by ");
ui.hyperlink_to("lunarydess", "https://github.com/lunarydess");
ui.label(" with ♡");
ui.with_layout(egui::Layout::right_to_left(Align::Center), |ui| {
ui.menu_image_button(egui::include_image!("cogwheel.svg"), |ui| {
// syntax selector
egui::ComboBox::from_label("Syntax")
.wrap_mode(TextWrapMode::Wrap)
.selected_text(format!("{:?}", &self.editor_syntax.language))
.show_ui(ui, |ui| {
[
Syntax::asm(),
Syntax::shell(),
Syntax::sql(),
Syntax::lua(),
Syntax::rust(),
Syntax::python(),
Syntax::java(),
]
.iter()
.for_each(|syntax| {
ui.selectable_value(
&mut self.editor_syntax,
syntax.clone(),
syntax.language,
);
});
});
// theme selector
let mut theme = ui.ctx().options(|opt| opt.theme_preference);
egui::ComboBox::from_label("Theme")
.wrap_mode(TextWrapMode::Wrap)
.selected_text(format!("{:?}", theme))
.show_ui(ui, |ui| {
ui.selectable_value(&mut theme, ThemePreference::System, "💻 System", );
ui.selectable_value(&mut theme, ThemePreference::Light, "☀ Light");
ui.selectable_value(&mut theme, ThemePreference::Dark, "🌙 Dark");
});
ui.ctx().set_theme(theme);
// scheme selector
egui::ComboBox::from_label("Scheme")
.wrap_mode(TextWrapMode::Wrap)
.selected_text(format!("{:?}", &self.editor_theme.name))
.show_ui(ui, |ui| {
DEFAULT_THEMES.iter().clone().for_each(|theme| {
ui.selectable_value(&mut self.editor_theme, *theme, theme.name);
});
});
});
});
});
});
}
fn save(&mut self, storage: &mut dyn eframe::Storage) {
eframe::set_value(storage, eframe::APP_KEY, self);
}
fn save(&mut self, storage: &mut dyn eframe::Storage) {
eframe::set_value(storage, eframe::APP_KEY, self);
}
}

View File

@@ -1,22 +1,21 @@
use application_catnip::CatnipApp;
use eframe::Renderer;
use eframe::{wgpu, Renderer};
fn main() {
env_logger::init();
eframe::run_native(
"Catnip Editor",
eframe::NativeOptions {
centered: true,
renderer: Renderer::Wgpu,
viewport: egui::ViewportBuilder::default()
.with_inner_size([400.0, 300.0])
.with_min_inner_size([300.0, 220.0]),
..Default::default()
},
Box::new(|context| {
egui_extras::install_image_loaders(&context.egui_ctx);
Ok(Box::<CatnipApp>::default())
}),
)
.expect("TODO: panic message");
env_logger::init();
eframe::run_native(
"Catnip Editor",
eframe::NativeOptions {
centered: true,
renderer: Renderer::Glow,
viewport: egui::ViewportBuilder::default()
.with_inner_size([400.0, 300.0])
.with_min_inner_size([300.0, 220.0]),
..Default::default()
},
Box::new(|context| {
egui_extras::install_image_loaders(&context.egui_ctx);
Ok(Box::<CatnipApp>::default())
}),
).expect("TODO: panic message");
}