Move default keybinds out of config
This commit is contained in:
parent
b97eb0603b
commit
48258645bb
4 changed files with 148 additions and 138 deletions
129
src/config.rs
129
src/config.rs
|
|
@ -2,68 +2,13 @@
|
|||
|
||||
use cosmic::{
|
||||
cosmic_config::{self, cosmic_config_derive::CosmicConfigEntry, CosmicConfigEntry},
|
||||
iced::keyboard::{KeyCode, Modifiers},
|
||||
theme,
|
||||
};
|
||||
use cosmic_text::Metrics;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::HashMap, fmt};
|
||||
|
||||
use crate::{ContextPage, Message};
|
||||
|
||||
pub const CONFIG_VERSION: u64 = 1;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub enum Action {
|
||||
CloseFile,
|
||||
CloseProject,
|
||||
Copy,
|
||||
Cut,
|
||||
Find,
|
||||
FindAndReplace,
|
||||
NewFile,
|
||||
NewWindow,
|
||||
OpenFileDialog,
|
||||
OpenProjectDialog,
|
||||
Paste,
|
||||
Quit,
|
||||
Redo,
|
||||
Save,
|
||||
SelectAll,
|
||||
ToggleGitManagement,
|
||||
ToggleProjectSearch,
|
||||
ToggleSettingsPage,
|
||||
ToggleWordWrap,
|
||||
Undo,
|
||||
}
|
||||
|
||||
impl Action {
|
||||
pub fn message(&self) -> Message {
|
||||
match self {
|
||||
Self::CloseFile => Message::CloseFile,
|
||||
Self::CloseProject => Message::CloseProject,
|
||||
Self::Copy => Message::Copy,
|
||||
Self::Cut => Message::Cut,
|
||||
Self::Find => Message::Find(Some(false)),
|
||||
Self::FindAndReplace => Message::Find(Some(true)),
|
||||
Self::NewFile => Message::NewFile,
|
||||
Self::NewWindow => Message::NewWindow,
|
||||
Self::OpenFileDialog => Message::OpenFileDialog,
|
||||
Self::OpenProjectDialog => Message::OpenProjectDialog,
|
||||
Self::Paste => Message::Paste,
|
||||
Self::Quit => Message::Quit,
|
||||
Self::Redo => Message::Redo,
|
||||
Self::Save => Message::Save,
|
||||
Self::SelectAll => Message::SelectAll,
|
||||
Self::ToggleGitManagement => Message::ToggleContextPage(ContextPage::GitManagement),
|
||||
Self::ToggleProjectSearch => Message::ToggleContextPage(ContextPage::ProjectSearch),
|
||||
Self::ToggleSettingsPage => Message::ToggleContextPage(ContextPage::Settings),
|
||||
Self::ToggleWordWrap => Message::ToggleWordWrap,
|
||||
Self::Undo => Message::Undo,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
pub enum AppTheme {
|
||||
Dark,
|
||||
|
|
@ -81,78 +26,6 @@ impl AppTheme {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub enum Modifier {
|
||||
Super,
|
||||
Ctrl,
|
||||
Alt,
|
||||
Shift,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub struct KeyBind {
|
||||
pub modifiers: Vec<Modifier>,
|
||||
pub key_code: KeyCode,
|
||||
}
|
||||
|
||||
impl KeyBind {
|
||||
//TODO: load from config
|
||||
pub fn load() -> HashMap<KeyBind, Action> {
|
||||
let mut keybinds = HashMap::new();
|
||||
|
||||
macro_rules! bind {
|
||||
([$($modifier:ident),+ $(,)?], $key_code:ident, $action:ident) => {{
|
||||
keybinds.insert(
|
||||
KeyBind {
|
||||
modifiers: vec![$(Modifier::$modifier),+],
|
||||
key_code: KeyCode::$key_code,
|
||||
},
|
||||
Action::$action,
|
||||
);
|
||||
}};
|
||||
}
|
||||
|
||||
bind!([Ctrl], W, CloseFile);
|
||||
bind!([Ctrl], X, Cut);
|
||||
bind!([Ctrl], C, Copy);
|
||||
bind!([Ctrl], F, Find);
|
||||
bind!([Ctrl], H, FindAndReplace);
|
||||
bind!([Ctrl], V, Paste);
|
||||
bind!([Ctrl], T, NewFile);
|
||||
bind!([Ctrl], N, NewWindow);
|
||||
bind!([Ctrl], O, OpenFileDialog);
|
||||
bind!([Ctrl, Shift], O, OpenProjectDialog);
|
||||
bind!([Ctrl], Q, Quit);
|
||||
bind!([Ctrl, Shift], Z, Redo);
|
||||
bind!([Ctrl], S, Save);
|
||||
bind!([Ctrl], A, SelectAll);
|
||||
bind!([Ctrl, Shift], G, ToggleGitManagement);
|
||||
bind!([Ctrl, Shift], F, ToggleProjectSearch);
|
||||
bind!([Ctrl], Comma, ToggleSettingsPage);
|
||||
bind!([Alt], Z, ToggleWordWrap);
|
||||
bind!([Ctrl], Z, Undo);
|
||||
|
||||
keybinds
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for KeyBind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
for modifier in self.modifiers.iter() {
|
||||
write!(f, "{:?} + ", modifier)?;
|
||||
}
|
||||
write!(f, "{:?}", self.key_code)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, CosmicConfigEntry, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
pub struct Config {
|
||||
pub app_theme: AppTheme,
|
||||
|
|
@ -165,7 +38,6 @@ pub struct Config {
|
|||
pub tab_width: u16,
|
||||
pub vim_bindings: bool,
|
||||
pub word_wrap: bool,
|
||||
pub keybinds: HashMap<KeyBind, Action>,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
|
|
@ -181,7 +53,6 @@ impl Default for Config {
|
|||
tab_width: 4,
|
||||
vim_bindings: false,
|
||||
word_wrap: false,
|
||||
keybinds: KeyBind::load(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
77
src/key_bind.rs
Normal file
77
src/key_bind.rs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
use cosmic::iced::keyboard::{KeyCode, Modifiers};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::HashMap, fmt};
|
||||
|
||||
use crate::Action;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub enum Modifier {
|
||||
Super,
|
||||
Ctrl,
|
||||
Alt,
|
||||
Shift,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub struct KeyBind {
|
||||
pub modifiers: Vec<Modifier>,
|
||||
pub key_code: KeyCode,
|
||||
}
|
||||
|
||||
impl KeyBind {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for KeyBind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
for modifier in self.modifiers.iter() {
|
||||
write!(f, "{:?} + ", modifier)?;
|
||||
}
|
||||
write!(f, "{:?}", self.key_code)
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: load from config
|
||||
pub fn key_binds() -> HashMap<KeyBind, Action> {
|
||||
let mut key_binds = HashMap::new();
|
||||
|
||||
macro_rules! bind {
|
||||
([$($modifier:ident),+ $(,)?], $key_code:ident, $action:ident) => {{
|
||||
key_binds.insert(
|
||||
KeyBind {
|
||||
modifiers: vec![$(Modifier::$modifier),+],
|
||||
key_code: KeyCode::$key_code,
|
||||
},
|
||||
Action::$action,
|
||||
);
|
||||
}};
|
||||
}
|
||||
|
||||
bind!([Ctrl], W, CloseFile);
|
||||
bind!([Ctrl], X, Cut);
|
||||
bind!([Ctrl], C, Copy);
|
||||
bind!([Ctrl], F, Find);
|
||||
bind!([Ctrl], H, FindAndReplace);
|
||||
bind!([Ctrl], V, Paste);
|
||||
bind!([Ctrl], T, NewFile);
|
||||
bind!([Ctrl], N, NewWindow);
|
||||
bind!([Ctrl], O, OpenFileDialog);
|
||||
bind!([Ctrl, Shift], O, OpenProjectDialog);
|
||||
bind!([Ctrl], Q, Quit);
|
||||
bind!([Ctrl, Shift], Z, Redo);
|
||||
bind!([Ctrl], S, Save);
|
||||
bind!([Ctrl], A, SelectAll);
|
||||
bind!([Ctrl, Shift], G, ToggleGitManagement);
|
||||
bind!([Ctrl, Shift], F, ToggleProjectSearch);
|
||||
bind!([Ctrl], Comma, ToggleSettingsPage);
|
||||
bind!([Alt], Z, ToggleWordWrap);
|
||||
bind!([Ctrl], Z, Undo);
|
||||
|
||||
key_binds
|
||||
}
|
||||
66
src/main.rs
66
src/main.rs
|
|
@ -18,8 +18,10 @@ use cosmic::{
|
|||
Application, ApplicationExt, Apply, Element,
|
||||
};
|
||||
use cosmic_text::{Cursor, Edit, Family, FontSystem, Selection, SwashCache, SyntaxSystem, ViMode};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
any::TypeId,
|
||||
collections::HashMap,
|
||||
env, fs, io,
|
||||
path::{Path, PathBuf},
|
||||
process,
|
||||
|
|
@ -27,7 +29,7 @@ use std::{
|
|||
};
|
||||
use tokio::time;
|
||||
|
||||
use config::{Action, AppTheme, Config, CONFIG_VERSION};
|
||||
use config::{AppTheme, Config, CONFIG_VERSION};
|
||||
mod config;
|
||||
|
||||
use git::{GitDiff, GitDiffLine, GitRepository, GitStatus, GitStatusKind};
|
||||
|
|
@ -36,6 +38,9 @@ mod git;
|
|||
use icon_cache::IconCache;
|
||||
mod icon_cache;
|
||||
|
||||
use key_bind::{key_binds, KeyBind};
|
||||
mod key_bind;
|
||||
|
||||
use line_number::LineNumberCache;
|
||||
mod line_number;
|
||||
|
||||
|
|
@ -149,6 +154,57 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub enum Action {
|
||||
CloseFile,
|
||||
CloseProject,
|
||||
Copy,
|
||||
Cut,
|
||||
Find,
|
||||
FindAndReplace,
|
||||
NewFile,
|
||||
NewWindow,
|
||||
OpenFileDialog,
|
||||
OpenProjectDialog,
|
||||
Paste,
|
||||
Quit,
|
||||
Redo,
|
||||
Save,
|
||||
SelectAll,
|
||||
ToggleGitManagement,
|
||||
ToggleProjectSearch,
|
||||
ToggleSettingsPage,
|
||||
ToggleWordWrap,
|
||||
Undo,
|
||||
}
|
||||
|
||||
impl Action {
|
||||
pub fn message(&self) -> Message {
|
||||
match self {
|
||||
Self::CloseFile => Message::CloseFile,
|
||||
Self::CloseProject => Message::CloseProject,
|
||||
Self::Copy => Message::Copy,
|
||||
Self::Cut => Message::Cut,
|
||||
Self::Find => Message::Find(Some(false)),
|
||||
Self::FindAndReplace => Message::Find(Some(true)),
|
||||
Self::NewFile => Message::NewFile,
|
||||
Self::NewWindow => Message::NewWindow,
|
||||
Self::OpenFileDialog => Message::OpenFileDialog,
|
||||
Self::OpenProjectDialog => Message::OpenProjectDialog,
|
||||
Self::Paste => Message::Paste,
|
||||
Self::Quit => Message::Quit,
|
||||
Self::Redo => Message::Redo,
|
||||
Self::Save => Message::Save,
|
||||
Self::SelectAll => Message::SelectAll,
|
||||
Self::ToggleGitManagement => Message::ToggleContextPage(ContextPage::GitManagement),
|
||||
Self::ToggleProjectSearch => Message::ToggleContextPage(ContextPage::ProjectSearch),
|
||||
Self::ToggleSettingsPage => Message::ToggleContextPage(ContextPage::Settings),
|
||||
Self::ToggleWordWrap => Message::ToggleWordWrap,
|
||||
Self::Undo => Message::Undo,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Flags {
|
||||
config_handler: Option<cosmic_config::Config>,
|
||||
|
|
@ -264,6 +320,7 @@ pub struct App {
|
|||
tab_model: segmented_button::SingleSelectModel,
|
||||
config_handler: Option<cosmic_config::Config>,
|
||||
config: Config,
|
||||
key_binds: HashMap<KeyBind, Action>,
|
||||
app_themes: Vec<String>,
|
||||
font_names: Vec<String>,
|
||||
font_size_names: Vec<String>,
|
||||
|
|
@ -970,6 +1027,7 @@ impl Application for App {
|
|||
tab_model: segmented_button::Model::builder().build(),
|
||||
config_handler: flags.config_handler,
|
||||
config: flags.config,
|
||||
key_binds: key_binds(),
|
||||
app_themes,
|
||||
font_names,
|
||||
font_size_names,
|
||||
|
|
@ -1281,7 +1339,7 @@ impl Application for App {
|
|||
self.git_project_status = Some(project_status);
|
||||
}
|
||||
Message::Key(modifiers, key_code) => {
|
||||
for (key_bind, action) in self.config.keybinds.iter() {
|
||||
for (key_bind, action) in self.key_binds.iter() {
|
||||
if key_bind.matches(modifiers, key_code) {
|
||||
return self.update(action.message());
|
||||
}
|
||||
|
|
@ -1765,7 +1823,7 @@ impl Application for App {
|
|||
}
|
||||
|
||||
fn header_start(&self) -> Vec<Element<Message>> {
|
||||
vec![menu_bar(&self.config)]
|
||||
vec![menu_bar(&self.config, &self.key_binds)]
|
||||
}
|
||||
|
||||
fn view(&self) -> Element<Message> {
|
||||
|
|
@ -1838,7 +1896,7 @@ impl Application for App {
|
|||
text_box = text_box.line_numbers();
|
||||
}
|
||||
let mut popover =
|
||||
widget::popover(text_box, menu::context_menu(&self.config, tab_id));
|
||||
widget::popover(text_box, menu::context_menu(&self.key_binds, tab_id));
|
||||
popover = match tab.context_menu {
|
||||
Some(position) => popover.position(position),
|
||||
None => popover.show_popup(false),
|
||||
|
|
|
|||
14
src/menu.rs
14
src/menu.rs
|
|
@ -14,8 +14,9 @@ use cosmic::{
|
|||
},
|
||||
Element,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{fl, icon_cache_get, Action, Config, ContextPage, Message};
|
||||
use crate::{fl, icon_cache_get, Action, Config, ContextPage, KeyBind, Message};
|
||||
|
||||
macro_rules! menu_button {
|
||||
($($x:expr),+ $(,)?) => (
|
||||
|
|
@ -32,10 +33,13 @@ macro_rules! menu_button {
|
|||
);
|
||||
}
|
||||
|
||||
pub fn context_menu<'a>(config: &Config, entity: segmented_button::Entity) -> Element<'a, Message> {
|
||||
pub fn context_menu<'a>(
|
||||
key_binds: &HashMap<KeyBind, Action>,
|
||||
entity: segmented_button::Entity,
|
||||
) -> Element<'a, Message> {
|
||||
let menu_item = |menu_label, menu_action| {
|
||||
let mut key = String::new();
|
||||
for (key_bind, key_action) in config.keybinds.iter() {
|
||||
for (key_bind, key_action) in key_binds.iter() {
|
||||
if key_action == &menu_action {
|
||||
key = key_bind.to_string();
|
||||
break;
|
||||
|
|
@ -76,7 +80,7 @@ pub fn context_menu<'a>(config: &Config, entity: segmented_button::Entity) -> El
|
|||
.into()
|
||||
}
|
||||
|
||||
pub fn menu_bar<'a>(config: &Config) -> Element<'a, Message> {
|
||||
pub fn menu_bar<'a>(config: &Config, key_binds: &HashMap<KeyBind, Action>) -> Element<'a, Message> {
|
||||
//TODO: port to libcosmic
|
||||
let menu_root = |label| {
|
||||
widget::button(widget::text(label))
|
||||
|
|
@ -89,7 +93,7 @@ pub fn menu_bar<'a>(config: &Config) -> Element<'a, Message> {
|
|||
|
||||
let find_key = |message: &Message| -> String {
|
||||
let mut key = String::new();
|
||||
for (key_bind, action) in config.keybinds.iter() {
|
||||
for (key_bind, action) in key_binds.iter() {
|
||||
if &action.message() == message {
|
||||
key = key_bind.to_string();
|
||||
break;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue