Compare commits

...

2 Commits

Author SHA1 Message Date
c658500d8b 🔥 rm flake.lock 2025-09-14 12:17:19 +02:00
6ee8b07d06 add flake.nix 2025-09-14 12:16:34 +02:00
4 changed files with 202 additions and 164 deletions

1
.gitignore vendored
View File

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

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)] #[derive(serde::Deserialize, serde::Serialize)]
#[serde(default)] #[serde(default)]
pub struct CatnipApp { pub struct CatnipApp {
label: String, label: String,
#[serde(skip)] #[serde(skip)]
editor_theme: ColorTheme, editor_theme: ColorTheme,
#[serde(skip)] #[serde(skip)]
editor_syntax: Syntax, editor_syntax: Syntax,
editor_text: String, editor_text: String,
#[serde(skip)] #[serde(skip)]
value: f32, value: f32,
} }
impl Default for CatnipApp { impl Default for CatnipApp {
fn default() -> Self { fn default() -> Self {
Self { Self {
label: "println!(\"meow\");".to_owned(), label: "println!(\"meow\");".to_owned(),
editor_theme: ColorTheme::default(), editor_theme: ColorTheme::default(),
editor_syntax: Syntax::default(), editor_syntax: Syntax::default(),
editor_text: "".to_owned(), editor_text: "".to_owned(),
value: 2.7, value: 2.7,
}
} }
}
} }
impl CatnipApp { impl CatnipApp {
pub fn new(cc: &eframe::CreationContext<'_>) -> Self { pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
if let Some(storage) = cc.storage { if let Some(storage) = cc.storage {
return eframe::get_value(storage, eframe::APP_KEY).unwrap_or_default(); return eframe::get_value(storage, eframe::APP_KEY).unwrap_or_default();
}
Default::default()
} }
Default::default()
}
} }
impl eframe::App for CatnipApp { impl eframe::App for CatnipApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
let modal = Modal::new(ctx, "open folder modal :3"); let modal = Modal::new(ctx, "open folder modal :3");
modal.show(|ui| { modal.show(|ui| {
modal.title(ui, "Hello world!"); modal.title(ui, "Hello world!");
modal.frame(ui, |ui| { modal.frame(ui, |ui| {
modal.body(ui, "This is a modal."); modal.body(ui, "This is a modal.");
}); });
modal.buttons(ui, |ui| { modal.buttons(ui, |ui| {
if modal.button(ui, "meow").clicked() {}; if modal.button(ui, "meow").clicked() {};
if modal.button(ui, "close").clicked() {}; if modal.button(ui, "close").clicked() {};
}); });
}); });
// top bar // top bar
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| { egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
egui::menu::bar(ui, |ui| { egui::menu::bar(ui, |ui| {
ui.menu_button("File", |ui| { ui.menu_button("File", |ui| {
ui.menu_button("New …", |_| {}); ui.menu_button("New …", |_| {});
ui.menu_button("Open …", |ui| { ui.menu_button("Open …", |ui| {
if ui.button("File").clicked() if ui.button("File").clicked()
&& let Some(path) = rfd::FileDialog::new().pick_file() && let Some(path) = rfd::FileDialog::new().pick_file()
{ {
self.editor_text = self.editor_text =
fs::read_to_string(path.display().to_string()).unwrap(); fs::read_to_string(path.display().to_string()).unwrap();
ui.close_kind(UiKind::Menu) ui.close_kind(UiKind::Menu)
} }
if ui.button("Folder").clicked() && !modal.is_open() { if ui.button("Folder").clicked() && !modal.is_open() {
modal.open(); modal.open();
ui.close_kind(UiKind::Menu) ui.close_kind(UiKind::Menu)
} }
}); });
if ui.button("Quit").clicked() { if ui.button("Quit").clicked() {
ctx.send_viewport_cmd(egui::ViewportCommand::Close); 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 fn save(&mut self, storage: &mut dyn eframe::Storage) {
egui::CentralPanel::default().show(ctx, |ui| { eframe::set_value(storage, eframe::APP_KEY, self);
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);
}
} }

View File

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