2023-11-03 16:16:24 -06:00
|
|
|
use cosmic::{
|
|
|
|
|
cosmic_config::{self, cosmic_config_derive::CosmicConfigEntry, CosmicConfigEntry},
|
|
|
|
|
iced::keyboard::{KeyCode, Modifiers},
|
|
|
|
|
};
|
2023-11-03 15:58:26 -06:00
|
|
|
use cosmic_text::Metrics;
|
2023-11-03 16:16:24 -06:00
|
|
|
use serde::{Deserialize, Serialize};
|
2023-10-30 10:19:52 -06:00
|
|
|
use std::{collections::HashMap, fmt};
|
|
|
|
|
|
2023-11-01 14:19:39 -06:00
|
|
|
use crate::{ContextPage, Message};
|
2023-10-30 10:19:52 -06:00
|
|
|
|
2023-11-03 18:45:03 -06:00
|
|
|
pub const CONFIG_VERSION: u64 = 1;
|
|
|
|
|
|
2023-11-03 16:16:24 -06:00
|
|
|
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
|
|
|
|
pub enum Action {
|
|
|
|
|
Cut,
|
|
|
|
|
Copy,
|
|
|
|
|
Paste,
|
|
|
|
|
NewFile,
|
|
|
|
|
NewWindow,
|
|
|
|
|
OpenFileDialog,
|
|
|
|
|
Save,
|
|
|
|
|
Quit,
|
|
|
|
|
ToggleSettingsPage,
|
|
|
|
|
ToggleWordWrap,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Action {
|
|
|
|
|
pub fn message(&self) -> Message {
|
|
|
|
|
match self {
|
|
|
|
|
Self::Cut => Message::Cut,
|
|
|
|
|
Self::Copy => Message::Copy,
|
|
|
|
|
Self::Paste => Message::Paste,
|
|
|
|
|
Self::NewFile => Message::NewFile,
|
|
|
|
|
Self::NewWindow => Message::NewWindow,
|
|
|
|
|
Self::OpenFileDialog => Message::OpenFileDialog,
|
|
|
|
|
Self::Save => Message::Save,
|
|
|
|
|
Self::Quit => Message::Quit,
|
|
|
|
|
Self::ToggleSettingsPage => Message::ToggleContextPage(ContextPage::Settings),
|
|
|
|
|
Self::ToggleWordWrap => Message::ToggleWordWrap,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
|
|
|
|
pub enum Modifier {
|
|
|
|
|
Super,
|
|
|
|
|
Ctrl,
|
|
|
|
|
Alt,
|
|
|
|
|
Shift,
|
|
|
|
|
}
|
2023-11-01 08:50:05 -06:00
|
|
|
|
2023-11-03 16:16:24 -06:00
|
|
|
#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
2023-10-30 10:19:52 -06:00
|
|
|
pub struct KeyBind {
|
2023-11-03 16:16:24 -06:00
|
|
|
pub modifiers: Vec<Modifier>,
|
2023-10-30 10:19:52 -06:00
|
|
|
pub key_code: KeyCode,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl KeyBind {
|
|
|
|
|
//TODO: load from config
|
2023-11-03 16:16:24 -06:00
|
|
|
pub fn load() -> HashMap<KeyBind, Action> {
|
2023-10-30 10:19:52 -06:00
|
|
|
let mut keybinds = HashMap::new();
|
|
|
|
|
|
|
|
|
|
macro_rules! bind {
|
2023-11-03 16:16:24 -06:00
|
|
|
([$($modifier:ident),+ $(,)?], $key_code:ident, $action:ident) => {{
|
2023-10-30 10:19:52 -06:00
|
|
|
keybinds.insert(
|
|
|
|
|
KeyBind {
|
2023-11-03 16:16:24 -06:00
|
|
|
modifiers: vec![$(Modifier::$modifier),+],
|
2023-10-30 10:19:52 -06:00
|
|
|
key_code: KeyCode::$key_code,
|
|
|
|
|
},
|
2023-11-03 16:16:24 -06:00
|
|
|
Action::$action,
|
2023-10-30 10:19:52 -06:00
|
|
|
);
|
|
|
|
|
}};
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-03 16:16:24 -06:00
|
|
|
bind!([Ctrl], X, Cut);
|
|
|
|
|
bind!([Ctrl], C, Copy);
|
|
|
|
|
bind!([Ctrl], V, Paste);
|
|
|
|
|
bind!([Ctrl], N, NewFile);
|
|
|
|
|
bind!([Ctrl, Shift], N, NewWindow);
|
|
|
|
|
bind!([Ctrl], O, OpenFileDialog);
|
|
|
|
|
bind!([Ctrl], S, Save);
|
|
|
|
|
bind!([Ctrl], Q, Quit);
|
|
|
|
|
bind!([Ctrl], Comma, ToggleSettingsPage);
|
|
|
|
|
bind!([Alt], Z, ToggleWordWrap);
|
2023-10-30 10:19:52 -06:00
|
|
|
|
|
|
|
|
keybinds
|
|
|
|
|
}
|
2023-11-03 16:16:24 -06:00
|
|
|
|
|
|
|
|
pub fn matches(&self, modifiers: Modifiers, key_code: KeyCode) -> bool {
|
|
|
|
|
self.key_code == key_code
|
|
|
|
|
&& modifiers.logo() == self.modifiers.contains(&Modifier::Super)
|
|
|
|
|
&& modifiers.control() == self.modifiers.contains(&Modifier::Ctrl)
|
|
|
|
|
&& modifiers.alt() == self.modifiers.contains(&Modifier::Alt)
|
|
|
|
|
&& modifiers.shift() == self.modifiers.contains(&Modifier::Shift)
|
|
|
|
|
}
|
2023-10-30 10:19:52 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl fmt::Display for KeyBind {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2023-11-03 16:16:24 -06:00
|
|
|
for modifier in self.modifiers.iter() {
|
|
|
|
|
write!(f, "{:?} + ", modifier)?;
|
2023-10-30 10:19:52 -06:00
|
|
|
}
|
|
|
|
|
write!(f, "{:?}", self.key_code)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-03 16:16:24 -06:00
|
|
|
#[derive(Clone, CosmicConfigEntry, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
2023-10-30 10:19:52 -06:00
|
|
|
pub struct Config {
|
2023-11-03 15:58:26 -06:00
|
|
|
pub font_size: u16,
|
2023-11-03 11:02:25 -06:00
|
|
|
pub syntax_theme_dark: String,
|
|
|
|
|
pub syntax_theme_light: String,
|
2023-11-01 14:19:39 -06:00
|
|
|
pub vim_bindings: bool,
|
2023-11-01 09:44:11 -06:00
|
|
|
pub word_wrap: bool,
|
2023-11-03 16:16:24 -06:00
|
|
|
pub keybinds: HashMap<KeyBind, Action>,
|
2023-10-30 10:19:52 -06:00
|
|
|
}
|
|
|
|
|
|
2023-11-03 16:16:24 -06:00
|
|
|
impl Default for Config {
|
|
|
|
|
fn default() -> Self {
|
2023-10-30 10:19:52 -06:00
|
|
|
Self {
|
2023-11-03 15:58:26 -06:00
|
|
|
font_size: 14,
|
2023-11-03 18:45:03 -06:00
|
|
|
syntax_theme_dark: "gruvbox-dark".to_string(),
|
|
|
|
|
syntax_theme_light: "gruvbox-light".to_string(),
|
2023-11-01 14:19:39 -06:00
|
|
|
vim_bindings: false,
|
2023-11-01 09:44:11 -06:00
|
|
|
word_wrap: false,
|
2023-10-30 10:19:52 -06:00
|
|
|
keybinds: KeyBind::load(),
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-03 16:16:24 -06:00
|
|
|
}
|
2023-11-03 11:02:25 -06:00
|
|
|
|
2023-11-03 16:16:24 -06:00
|
|
|
impl Config {
|
2023-11-03 15:58:26 -06:00
|
|
|
// Calculate metrics from font size
|
|
|
|
|
pub fn metrics(&self) -> Metrics {
|
|
|
|
|
let font_size = self.font_size as f32;
|
|
|
|
|
let line_height = (font_size * 1.4).ceil();
|
|
|
|
|
Metrics::new(font_size, line_height)
|
2023-11-03 11:02:25 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get current syntax theme based on dark mode
|
|
|
|
|
pub fn syntax_theme(&self, dark: bool) -> &str {
|
|
|
|
|
if dark {
|
|
|
|
|
&self.syntax_theme_dark
|
|
|
|
|
} else {
|
|
|
|
|
&self.syntax_theme_light
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-10-30 10:19:52 -06:00
|
|
|
}
|