make config (de)serializable
This commit is contained in:
Generated
+60
@@ -70,6 +70,9 @@ name = "bitflags"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
@@ -158,6 +161,7 @@ dependencies = [
|
||||
"mio",
|
||||
"parking_lot",
|
||||
"rustix",
|
||||
"serde",
|
||||
"signal-hook",
|
||||
"signal-hook-mio",
|
||||
"winapi",
|
||||
@@ -438,6 +442,8 @@ dependencies = [
|
||||
"crossterm",
|
||||
"itertools",
|
||||
"ratatui",
|
||||
"serde",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1101,6 +1107,15 @@ dependencies = [
|
||||
"zmij",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.9"
|
||||
@@ -1333,6 +1348,45 @@ version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca"
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "1.1.2+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde_core",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_parser",
|
||||
"toml_writer",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "1.1.1+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.1.2+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_writer"
|
||||
version = "1.1.1+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.19.0"
|
||||
@@ -1625,6 +1679,12 @@ dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5"
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen"
|
||||
version = "0.51.0"
|
||||
|
||||
+3
-1
@@ -4,6 +4,8 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
crossterm = "0.29.0"
|
||||
crossterm = { version = "0.29.0", features = ["serde"] }
|
||||
itertools = "0.14.0"
|
||||
ratatui = "0.30.0"
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
toml = "1.1.2"
|
||||
|
||||
+286
-4
@@ -1,16 +1,41 @@
|
||||
use std::{cmp::min, collections::hash_set::Entry, convert::identity, fs::File, io::Write, iter, mem::{replace, swap}};
|
||||
use ratatui::{style::{Color, Stylize}, text::Span};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::{BYTES_OF_PADDING, BYTES_PER_LINE, LINES_OF_PADDING, app::WindowSize, buffer::{Buffer, Mode, PartialAction, Popup}, cursor::Cursor, edit_action::EditAction};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Serialize, Deserialize)]
|
||||
#[derive(Debug)]
|
||||
#[serde(into = "&str")]
|
||||
#[serde(try_from = "&str")]
|
||||
pub enum Action {
|
||||
App(AppAction),
|
||||
Buffer(BufferAction),
|
||||
Cursor(CursorAction),
|
||||
}
|
||||
|
||||
impl From<Action> for &str {
|
||||
fn from(action: Action) -> Self {
|
||||
match action {
|
||||
Action::App(app_action) => app_action.into(),
|
||||
Action::Buffer(buffer_action) => buffer_action.into(),
|
||||
Action::Cursor(cursor_action) => cursor_action.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for Action {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(string: &str) -> Result<Self, String> {
|
||||
AppAction::try_from(string).map(Action::from)
|
||||
.or_else(|_| BufferAction::try_from(string).map(Action::from))
|
||||
.or_else(|_| CursorAction::try_from(string).map(Action::from))
|
||||
.map_err(|_| format!("invalid action: {}", string))
|
||||
}
|
||||
}
|
||||
|
||||
// actions that act on the app as a whole, not just one buffer
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, Deserialize)]
|
||||
pub enum AppAction {
|
||||
QuitIfSaved,
|
||||
Quit,
|
||||
@@ -21,13 +46,50 @@ pub enum AppAction {
|
||||
Yank,
|
||||
}
|
||||
|
||||
impl From<AppAction> for &str {
|
||||
fn from(app_action: AppAction) -> Self {
|
||||
use AppAction::*;
|
||||
|
||||
match app_action {
|
||||
QuitIfSaved => "quit_if_saved",
|
||||
Quit => "quit",
|
||||
|
||||
PreviousBuffer => "previous_buffer",
|
||||
NextBuffer => "next_buffer",
|
||||
|
||||
Yank => "yank",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AppAction> for Action {
|
||||
fn from(app_action: AppAction) -> Self {
|
||||
Self::App(app_action)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
impl TryFrom<&str> for AppAction {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(string: &str) -> Result<Self, ()> {
|
||||
use AppAction::*;
|
||||
|
||||
match string {
|
||||
"quit_if_saved" => Ok(QuitIfSaved),
|
||||
"quit" => Ok(Quit),
|
||||
|
||||
"previous_buffer" => Ok(PreviousBuffer),
|
||||
"next_buffer" => Ok(NextBuffer),
|
||||
|
||||
"yank" => Ok(Yank),
|
||||
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Deserialize)]
|
||||
#[derive(Debug)]
|
||||
pub enum BufferAction {
|
||||
NormalMode,
|
||||
SelectMode,
|
||||
@@ -93,13 +155,161 @@ pub enum BufferAction {
|
||||
InspectSelectionColor,
|
||||
}
|
||||
|
||||
impl From<BufferAction> for &str {
|
||||
fn from(buffer_action: BufferAction) -> Self {
|
||||
use BufferAction::*;
|
||||
|
||||
match buffer_action {
|
||||
NormalMode => "normal_mode",
|
||||
SelectMode => "select_mode",
|
||||
|
||||
Goto => "goto",
|
||||
View => "view",
|
||||
Replace => "replace",
|
||||
Space => "space",
|
||||
Repeat => "repeat",
|
||||
To => "to",
|
||||
|
||||
ScrollDown => "scroll_down",
|
||||
ScrollUp => "scroll_up",
|
||||
|
||||
PageCursorHalfDown => "page_cursor_half_down",
|
||||
PageCursorHalfUp => "page_cursor_half_up",
|
||||
|
||||
PageDown => "page_down",
|
||||
PageUp => "page_up",
|
||||
|
||||
CollapseSelection => "collapse_selection",
|
||||
FlipSelections => "flip_selections",
|
||||
|
||||
Delete => "delete",
|
||||
|
||||
Undo => "undo",
|
||||
Redo => "redo",
|
||||
|
||||
Save => "save",
|
||||
|
||||
CopySelectionOnNextLine => "copy_selection_on_next_line",
|
||||
|
||||
RotateSelectionsBackward => "rotate_selections_backward",
|
||||
RotateSelectionsForward => "rotate_selections_forward",
|
||||
|
||||
KeepPrimarySelection => "keep_primary_selection",
|
||||
RemovePrimarySelection => "remove_primary_selection",
|
||||
|
||||
SplitSelectionsInto1s => "split_selections_into_1_s",
|
||||
SplitSelectionsInto2s => "split_selections_into_2_s",
|
||||
SplitSelectionsInto3s => "split_selections_into_3_s",
|
||||
SplitSelectionsInto4s => "split_selections_into_4_s",
|
||||
SplitSelectionsInto5s => "split_selections_into_5_s",
|
||||
SplitSelectionsInto6s => "split_selections_into_6_s",
|
||||
SplitSelectionsInto7s => "split_selections_into_7_s",
|
||||
SplitSelectionsInto8s => "split_selections_into_8_s",
|
||||
SplitSelectionsInto9s => "split_selections_into_9_s",
|
||||
|
||||
JumpToSelectedOffset => "jump_to_selected_offset",
|
||||
JumpToSelectedOffsetRelativeToMark => "jump_to_selected_offset_relative_to_mark",
|
||||
|
||||
ToggleMark => "toggle_mark",
|
||||
|
||||
AlignViewCenter => "align_view_center",
|
||||
AlignViewBottom => "align_view_bottom",
|
||||
AlignViewTop => "align_view_top",
|
||||
|
||||
ExtendToMark => "extend_to_mark",
|
||||
ExtendToNull => "extend_to_null",
|
||||
ExtendToFF => "extend_to_ff",
|
||||
|
||||
InspectSelection => "inspect_selection",
|
||||
InspectSelectionColor => "inspect_selection_color",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BufferAction> for Action {
|
||||
fn from(buffer_action: BufferAction) -> Self {
|
||||
Self::Buffer(buffer_action)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
impl TryFrom<&str> for BufferAction {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(string: &str) -> Result<Self, ()> {
|
||||
use BufferAction::*;
|
||||
|
||||
match string {
|
||||
"normal_mode" => Ok(NormalMode),
|
||||
"select_mode" => Ok(SelectMode),
|
||||
|
||||
"goto" => Ok(Goto),
|
||||
"view" => Ok(View),
|
||||
"replace" => Ok(Replace),
|
||||
"space" => Ok(Space),
|
||||
"repeat" => Ok(Repeat),
|
||||
"to" => Ok(To),
|
||||
|
||||
"scroll_down" => Ok(ScrollDown),
|
||||
"scroll_up" => Ok(ScrollUp),
|
||||
|
||||
"page_cursor_half_down" => Ok(PageCursorHalfDown),
|
||||
"page_cursor_half_up" => Ok(PageCursorHalfUp),
|
||||
|
||||
"page_down" => Ok(PageDown),
|
||||
"page_up" => Ok(PageUp),
|
||||
|
||||
"collapse_selection" => Ok(CollapseSelection),
|
||||
"flip_selections" => Ok(FlipSelections),
|
||||
|
||||
"delete" => Ok(Delete),
|
||||
|
||||
"undo" => Ok(Undo),
|
||||
"redo" => Ok(Redo),
|
||||
|
||||
"save" => Ok(Save),
|
||||
|
||||
"copy_selection_on_next_line" => Ok(CopySelectionOnNextLine),
|
||||
|
||||
"rotate_selections_backward" => Ok(RotateSelectionsBackward),
|
||||
"rotate_selections_forward" => Ok(RotateSelectionsForward),
|
||||
|
||||
"keep_primary_selection" => Ok(KeepPrimarySelection),
|
||||
"remove_primary_selection" => Ok(RemovePrimarySelection),
|
||||
|
||||
"split_selections_into_1_s" => Ok(SplitSelectionsInto1s),
|
||||
"split_selections_into_2_s" => Ok(SplitSelectionsInto2s),
|
||||
"split_selections_into_3_s" => Ok(SplitSelectionsInto3s),
|
||||
"split_selections_into_4_s" => Ok(SplitSelectionsInto4s),
|
||||
"split_selections_into_5_s" => Ok(SplitSelectionsInto5s),
|
||||
"split_selections_into_6_s" => Ok(SplitSelectionsInto6s),
|
||||
"split_selections_into_7_s" => Ok(SplitSelectionsInto7s),
|
||||
"split_selections_into_8_s" => Ok(SplitSelectionsInto8s),
|
||||
"split_selections_into_9_s" => Ok(SplitSelectionsInto9s),
|
||||
|
||||
"jump_to_selected_offset" => Ok(JumpToSelectedOffset),
|
||||
"jump_to_selected_offset_relative_to_mark" => Ok(JumpToSelectedOffsetRelativeToMark),
|
||||
|
||||
"toggle_mark" => Ok(ToggleMark),
|
||||
|
||||
"align_view_center" => Ok(AlignViewCenter),
|
||||
"align_view_bottom" => Ok(AlignViewBottom),
|
||||
"align_view_top" => Ok(AlignViewTop),
|
||||
|
||||
"extend_to_mark" => Ok(ExtendToMark),
|
||||
"extend_to_null" => Ok(ExtendToNull),
|
||||
"extend_to_ff" => Ok(ExtendToFF),
|
||||
|
||||
"inspect_selection" => Ok(InspectSelection),
|
||||
"inspect_selection_color" => Ok(InspectSelectionColor),
|
||||
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Serialize, Deserialize)]
|
||||
#[derive(Debug)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum CursorAction {
|
||||
MoveByteUp,
|
||||
MoveByteDown,
|
||||
@@ -128,12 +338,84 @@ pub enum CursorAction {
|
||||
ExtendLineAbove,
|
||||
}
|
||||
|
||||
impl From<CursorAction> for &str {
|
||||
fn from(cursor_action: CursorAction) -> Self {
|
||||
use CursorAction::*;
|
||||
|
||||
match cursor_action {
|
||||
MoveByteUp => "move_byte_up",
|
||||
MoveByteDown => "move_byte_down",
|
||||
MoveByteLeft => "move_byte_left",
|
||||
MoveByteRight => "move_byte_right",
|
||||
|
||||
ExtendByteUp => "extend_byte_up",
|
||||
ExtendByteDown => "extend_byte_down",
|
||||
ExtendByteLeft => "extend_byte_left",
|
||||
ExtendByteRight => "extend_byte_right",
|
||||
|
||||
GotoLineStart => "goto_line_start",
|
||||
GotoLineEnd => "goto_line_end",
|
||||
GotoFileStart => "goto_file_start",
|
||||
GotoFileEnd => "goto_file_end",
|
||||
|
||||
MoveNextWordStart => "move_next_word_start",
|
||||
MoveNextWordEnd => "move_next_word_end",
|
||||
MovePreviousWordStart => "move_previous_word_start",
|
||||
|
||||
ExtendNextWordStart => "extend_next_word_start",
|
||||
ExtendNextWordEnd => "extend_next_word_end",
|
||||
ExtendPreviousWordStart => "extend_previous_word_start",
|
||||
|
||||
ExtendLineBelow => "extend_line_below",
|
||||
ExtendLineAbove => "extend_line_above",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CursorAction> for Action {
|
||||
fn from(cursor_action: CursorAction) -> Self {
|
||||
Self::Cursor(cursor_action)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for CursorAction {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(string: &str) -> Result<Self, ()> {
|
||||
use CursorAction::*;
|
||||
|
||||
match string {
|
||||
"move_byte_up" => Ok(MoveByteUp),
|
||||
"move_byte_down" => Ok(MoveByteDown),
|
||||
"move_byte_left" => Ok(MoveByteLeft),
|
||||
"move_byte_right" => Ok(MoveByteRight),
|
||||
|
||||
"extend_byte_up" => Ok(ExtendByteUp),
|
||||
"extend_byte_down" => Ok(ExtendByteDown),
|
||||
"extend_byte_left" => Ok(ExtendByteLeft),
|
||||
"extend_byte_right" => Ok(ExtendByteRight),
|
||||
|
||||
"goto_line_start" => Ok(GotoLineStart),
|
||||
"goto_line_end" => Ok(GotoLineEnd),
|
||||
"goto_file_start" => Ok(GotoFileStart),
|
||||
"goto_file_end" => Ok(GotoFileEnd),
|
||||
|
||||
"move_next_word_start" => Ok(MoveNextWordStart),
|
||||
"move_next_word_end" => Ok(MoveNextWordEnd),
|
||||
"move_previous_word_start" => Ok(MovePreviousWordStart),
|
||||
|
||||
"extend_next_word_start" => Ok(ExtendNextWordStart),
|
||||
"extend_next_word_end" => Ok(ExtendNextWordEnd),
|
||||
"extend_previous_word_start" => Ok(ExtendPreviousWordStart),
|
||||
|
||||
"extend_line_below" => Ok(ExtendLineBelow),
|
||||
"extend_line_above" => Ok(ExtendLineAbove),
|
||||
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
pub fn execute(&mut self, action: BufferAction, window_size: WindowSize) {
|
||||
match action {
|
||||
|
||||
+33
-8
@@ -2,6 +2,7 @@ use core::slice::GetDisjointMutIndex;
|
||||
use std::{collections::HashSet, fs::File, io::Read, path::PathBuf};
|
||||
use crossterm::event::KeyEvent;
|
||||
use ratatui::{layout::{Constraint, Rect}, style::{Color, Stylize}, text::Span, widgets::{Block, Clear, Widget}};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::{BYTES_PER_LINE, action::{Action, AppAction, bytes_to_nat}, app::WindowSize, config::Config, cursor::Cursor, edit_action::EditAction};
|
||||
|
||||
mod widget;
|
||||
@@ -36,12 +37,16 @@ pub struct Buffer {
|
||||
pub logs: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum Mode {
|
||||
Normal, Select, Insert
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum PartialAction {
|
||||
Goto, View, Replace, Space, Repeat, To
|
||||
}
|
||||
@@ -73,13 +78,33 @@ impl Mode {
|
||||
|
||||
impl PartialAction {
|
||||
pub const fn label(self) -> &'static str {
|
||||
use PartialAction::*;
|
||||
|
||||
match self {
|
||||
Self::Goto => "g",
|
||||
Self::View => "z",
|
||||
Self::Replace => "r",
|
||||
Self::Space => "␠",
|
||||
Self::Repeat => "×",
|
||||
Self::To => "t",
|
||||
Goto => "g",
|
||||
View => "z",
|
||||
Replace => "r",
|
||||
Space => "␠",
|
||||
Repeat => "×",
|
||||
To => "t",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for PartialAction {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
use PartialAction::*;
|
||||
|
||||
match value {
|
||||
"goto" => Ok(Goto),
|
||||
"view" => Ok(View),
|
||||
"replace" => Ok(Replace),
|
||||
"space" => Ok(Space),
|
||||
"repeat" => Ok(Repeat),
|
||||
"to" => Ok(To),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+287
-159
@@ -1,25 +1,114 @@
|
||||
use std::collections::HashMap;
|
||||
use std::{collections::{HashMap, hash_map::Entry}, fmt::{self, Formatter}};
|
||||
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
||||
use crate::{action::{Action, AppAction, BufferAction, CursorAction}, buffer::{Mode, PartialAction}};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::{Error, MapAccess, Unexpected, Visitor}, ser::SerializeMap};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct Config(
|
||||
pub HashMap<Mode, ModeConfig>
|
||||
);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ModeConfig(
|
||||
pub HashMap<Option<PartialAction>, Keybinds>
|
||||
);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug)]
|
||||
#[serde(transparent)]
|
||||
pub struct Keybinds(
|
||||
pub HashMap<Keypress, Action>
|
||||
);
|
||||
|
||||
#[derive(PartialEq, Eq, Hash)]
|
||||
#[derive(PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug)]
|
||||
#[serde(into = "String")]
|
||||
#[serde(try_from = "&str")]
|
||||
pub struct Keypress {
|
||||
code: KeyCode,
|
||||
modifiers: KeyModifiers
|
||||
}
|
||||
|
||||
impl Serialize for ModeConfig {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut map = serializer.serialize_map(None)?;
|
||||
|
||||
if let Some(keybinds) = self.0.get(&None) {
|
||||
for (keypress, action) in &keybinds.0 {
|
||||
map.serialize_entry(
|
||||
&String::from(keypress),
|
||||
&action
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
for (partial_action, keybinds) in &self.0 {
|
||||
let Some(partial_action) = partial_action else { continue };
|
||||
|
||||
map.serialize_entry(
|
||||
partial_action.into(),
|
||||
keybinds
|
||||
)?;
|
||||
}
|
||||
|
||||
map.end()
|
||||
}
|
||||
}
|
||||
|
||||
struct ModeConfigVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for ModeConfigVisitor {
|
||||
type Value = ModeConfig;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
formatter.write_str("a config for keypresses in various partial action states")
|
||||
}
|
||||
|
||||
fn visit_map<Map: MapAccess<'de>>(
|
||||
self,
|
||||
mut map: Map
|
||||
) -> Result<Self::Value, Map::Error> {
|
||||
let mut result = ModeConfig(HashMap::new());
|
||||
|
||||
while let Some(key) = map.next_key::<&str>()? {
|
||||
if let Ok(partial_action) = PartialAction::try_from(key) {
|
||||
let keybinds: Keybinds = map.next_value()?;
|
||||
|
||||
match result.0.entry(Some(partial_action)) {
|
||||
Entry::Occupied(mut occupied_entry) => {
|
||||
occupied_entry.get_mut().0.extend(keybinds.0);
|
||||
},
|
||||
Entry::Vacant(vacant_entry) => {
|
||||
vacant_entry.insert(keybinds);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let Ok(keypress) = key.try_into() else {
|
||||
return Err(Error::invalid_value(
|
||||
Unexpected::Str(key),
|
||||
&"a valid keypress, with an optional modifier"
|
||||
));
|
||||
};
|
||||
|
||||
result.0.entry(None)
|
||||
.or_insert_with(|| Keybinds(HashMap::new()))
|
||||
.0.insert(keypress, map.next_value()?);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for ModeConfig {
|
||||
fn deserialize<D: Deserializer<'de>>(
|
||||
deserializer: D
|
||||
) -> Result<Self, D::Error> {
|
||||
deserializer.deserialize_map(ModeConfigVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> From<[(Mode, ModeConfig); N]> for Config {
|
||||
fn from(array: [(Mode, ModeConfig); N]) -> Self {
|
||||
Self(array.into())
|
||||
@@ -55,11 +144,30 @@ const fn modifier_from_character(character: char) -> Option<KeyModifiers> {
|
||||
}
|
||||
}
|
||||
|
||||
const fn str_from_modifiers(modifier: KeyModifiers) -> &'static str {
|
||||
match modifier {
|
||||
KeyModifiers::ALT => "A-",
|
||||
KeyModifiers::CONTROL => "C-",
|
||||
_ => ""
|
||||
}
|
||||
}
|
||||
|
||||
fn string_from_code(code: KeyCode) -> String {
|
||||
match code {
|
||||
KeyCode::Char(character) => character.to_string(),
|
||||
KeyCode::Up => "Up".to_string(),
|
||||
KeyCode::Down => "Down".to_string(),
|
||||
KeyCode::Left => "Left".to_string(),
|
||||
KeyCode::Right => "Right".to_string(),
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for Keypress {
|
||||
type Error = ();
|
||||
type Error = String;
|
||||
|
||||
fn try_from(string: &str) -> Result<Self, ()> {
|
||||
match string.len() {
|
||||
fn try_from(string: &str) -> Result<Self, Self::Error> {
|
||||
match string.chars().count() {
|
||||
3 => {
|
||||
Ok(Self {
|
||||
code: KeyCode::Char(
|
||||
@@ -67,7 +175,7 @@ impl TryFrom<&str> for Keypress {
|
||||
),
|
||||
modifiers: modifier_from_character(
|
||||
string.chars().nth(0).unwrap()
|
||||
).ok_or(())?,
|
||||
).ok_or(format!("unknown modifier: {}", string.chars().nth(0).unwrap()))?,
|
||||
})
|
||||
}
|
||||
1 => {
|
||||
@@ -77,11 +185,27 @@ impl TryFrom<&str> for Keypress {
|
||||
).into()
|
||||
)
|
||||
}
|
||||
_ => Err(())
|
||||
_ => Err(format!("invalid keypress: {}. only one modifier is allowed", string))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Keypress> for String {
|
||||
fn from(value: &Keypress) -> Self {
|
||||
format!(
|
||||
"{}{}",
|
||||
str_from_modifiers(value.modifiers),
|
||||
string_from_code(value.code)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Keypress> for String {
|
||||
fn from(value: Keypress) -> Self {
|
||||
String::from(&value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<KeyEvent> for Keypress {
|
||||
fn from(event: KeyEvent) -> Self {
|
||||
Self {
|
||||
@@ -94,238 +218,242 @@ impl From<KeyEvent> for Keypress {
|
||||
impl Default for Config {
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn default() -> Self {
|
||||
use AppAction::*;
|
||||
use BufferAction::*;
|
||||
use CursorAction::*;
|
||||
|
||||
[
|
||||
(Mode::Normal, [
|
||||
(None, [
|
||||
("q".try_into().unwrap(), AppAction::QuitIfSaved.into()),
|
||||
("Q".try_into().unwrap(), AppAction::Quit.into()),
|
||||
("q".try_into().unwrap(), QuitIfSaved.into()),
|
||||
("Q".try_into().unwrap(), Quit.into()),
|
||||
|
||||
("v".try_into().unwrap(), BufferAction::SelectMode.into()),
|
||||
("v".try_into().unwrap(), SelectMode.into()),
|
||||
|
||||
("g".try_into().unwrap(), BufferAction::Goto.into()),
|
||||
("z".try_into().unwrap(), BufferAction::View.into()),
|
||||
("r".try_into().unwrap(), BufferAction::Replace.into()),
|
||||
(" ".try_into().unwrap(), BufferAction::Space.into()),
|
||||
("*".try_into().unwrap(), BufferAction::Repeat.into()),
|
||||
("t".try_into().unwrap(), BufferAction::To.into()),
|
||||
("g".try_into().unwrap(), Goto.into()),
|
||||
("z".try_into().unwrap(), View.into()),
|
||||
("r".try_into().unwrap(), Replace.into()),
|
||||
(" ".try_into().unwrap(), Space.into()),
|
||||
("*".try_into().unwrap(), Repeat.into()),
|
||||
("t".try_into().unwrap(), To.into()),
|
||||
|
||||
("i".try_into().unwrap(), CursorAction::MoveByteUp.into()),
|
||||
("k".try_into().unwrap(), CursorAction::MoveByteDown.into()),
|
||||
("j".try_into().unwrap(), CursorAction::MoveByteLeft.into()),
|
||||
("l".try_into().unwrap(), CursorAction::MoveByteRight.into()),
|
||||
("i".try_into().unwrap(), MoveByteUp.into()),
|
||||
("k".try_into().unwrap(), MoveByteDown.into()),
|
||||
("j".try_into().unwrap(), MoveByteLeft.into()),
|
||||
("l".try_into().unwrap(), MoveByteRight.into()),
|
||||
|
||||
("G".try_into().unwrap(), CursorAction::GotoFileEnd.into()),
|
||||
("G".try_into().unwrap(), GotoFileEnd.into()),
|
||||
|
||||
("C-e".try_into().unwrap(), BufferAction::ScrollDown.into()),
|
||||
("C-y".try_into().unwrap(), BufferAction::ScrollUp.into()),
|
||||
("C-e".try_into().unwrap(), ScrollDown.into()),
|
||||
("C-y".try_into().unwrap(), ScrollUp.into()),
|
||||
|
||||
("C-d".try_into().unwrap(), BufferAction::PageCursorHalfDown.into()),
|
||||
("C-u".try_into().unwrap(), BufferAction::PageCursorHalfUp.into()),
|
||||
("C-d".try_into().unwrap(), PageCursorHalfDown.into()),
|
||||
("C-u".try_into().unwrap(), PageCursorHalfUp.into()),
|
||||
|
||||
("C-f".try_into().unwrap(), BufferAction::PageDown.into()),
|
||||
("C-b".try_into().unwrap(), BufferAction::PageUp.into()),
|
||||
("C-f".try_into().unwrap(), PageDown.into()),
|
||||
("C-b".try_into().unwrap(), PageUp.into()),
|
||||
|
||||
("w".try_into().unwrap(), CursorAction::MoveNextWordStart.into()),
|
||||
("e".try_into().unwrap(), CursorAction::MoveNextWordEnd.into()),
|
||||
("b".try_into().unwrap(), CursorAction::MovePreviousWordStart.into()),
|
||||
("w".try_into().unwrap(), MoveNextWordStart.into()),
|
||||
("e".try_into().unwrap(), MoveNextWordEnd.into()),
|
||||
("b".try_into().unwrap(), MovePreviousWordStart.into()),
|
||||
|
||||
(";".try_into().unwrap(), BufferAction::CollapseSelection.into()),
|
||||
("A-;".try_into().unwrap(), BufferAction::FlipSelections.into()),
|
||||
(";".try_into().unwrap(), CollapseSelection.into()),
|
||||
("A-;".try_into().unwrap(), FlipSelections.into()),
|
||||
|
||||
("x".try_into().unwrap(), CursorAction::ExtendLineBelow.into()),
|
||||
("X".try_into().unwrap(), CursorAction::ExtendLineAbove.into()),
|
||||
("x".try_into().unwrap(), ExtendLineBelow.into()),
|
||||
("X".try_into().unwrap(), ExtendLineAbove.into()),
|
||||
|
||||
("d".try_into().unwrap(), BufferAction::Delete.into()),
|
||||
("d".try_into().unwrap(), Delete.into()),
|
||||
|
||||
("u".try_into().unwrap(), BufferAction::Undo.into()),
|
||||
("U".try_into().unwrap(), BufferAction::Redo.into()),
|
||||
("u".try_into().unwrap(), Undo.into()),
|
||||
("U".try_into().unwrap(), Redo.into()),
|
||||
|
||||
("C-j".try_into().unwrap(), AppAction::PreviousBuffer.into()),
|
||||
("C-l".try_into().unwrap(), AppAction::NextBuffer.into()),
|
||||
("C-j".try_into().unwrap(), PreviousBuffer.into()),
|
||||
("C-l".try_into().unwrap(), NextBuffer.into()),
|
||||
|
||||
("C".try_into().unwrap(), BufferAction::CopySelectionOnNextLine.into()),
|
||||
("C".try_into().unwrap(), CopySelectionOnNextLine.into()),
|
||||
|
||||
("(".try_into().unwrap(), BufferAction::RotateSelectionsBackward.into()),
|
||||
(")".try_into().unwrap(), BufferAction::RotateSelectionsForward.into()),
|
||||
("(".try_into().unwrap(), RotateSelectionsBackward.into()),
|
||||
(")".try_into().unwrap(), RotateSelectionsForward.into()),
|
||||
|
||||
(",".try_into().unwrap(), BufferAction::KeepPrimarySelection.into()),
|
||||
("A-,".try_into().unwrap(), BufferAction::RemovePrimarySelection.into()),
|
||||
(",".try_into().unwrap(), KeepPrimarySelection.into()),
|
||||
("A-,".try_into().unwrap(), RemovePrimarySelection.into()),
|
||||
|
||||
("1".try_into().unwrap(), BufferAction::SplitSelectionsInto1s.into()),
|
||||
("2".try_into().unwrap(), BufferAction::SplitSelectionsInto2s.into()),
|
||||
("3".try_into().unwrap(), BufferAction::SplitSelectionsInto3s.into()),
|
||||
("4".try_into().unwrap(), BufferAction::SplitSelectionsInto4s.into()),
|
||||
("5".try_into().unwrap(), BufferAction::SplitSelectionsInto5s.into()),
|
||||
("6".try_into().unwrap(), BufferAction::SplitSelectionsInto6s.into()),
|
||||
("7".try_into().unwrap(), BufferAction::SplitSelectionsInto7s.into()),
|
||||
("8".try_into().unwrap(), BufferAction::SplitSelectionsInto8s.into()),
|
||||
("9".try_into().unwrap(), BufferAction::SplitSelectionsInto9s.into()),
|
||||
("1".try_into().unwrap(), SplitSelectionsInto1s.into()),
|
||||
("2".try_into().unwrap(), SplitSelectionsInto2s.into()),
|
||||
("3".try_into().unwrap(), SplitSelectionsInto3s.into()),
|
||||
("4".try_into().unwrap(), SplitSelectionsInto4s.into()),
|
||||
("5".try_into().unwrap(), SplitSelectionsInto5s.into()),
|
||||
("6".try_into().unwrap(), SplitSelectionsInto6s.into()),
|
||||
("7".try_into().unwrap(), SplitSelectionsInto7s.into()),
|
||||
("8".try_into().unwrap(), SplitSelectionsInto8s.into()),
|
||||
("9".try_into().unwrap(), SplitSelectionsInto9s.into()),
|
||||
|
||||
("J".try_into().unwrap(), BufferAction::JumpToSelectedOffsetRelativeToMark.into()),
|
||||
("A-J".try_into().unwrap(), BufferAction::JumpToSelectedOffset.into()),
|
||||
("J".try_into().unwrap(), JumpToSelectedOffsetRelativeToMark.into()),
|
||||
("A-J".try_into().unwrap(), JumpToSelectedOffset.into()),
|
||||
|
||||
("m".try_into().unwrap(), BufferAction::ToggleMark.into()),
|
||||
("m".try_into().unwrap(), ToggleMark.into()),
|
||||
|
||||
("y".try_into().unwrap(), AppAction::Yank.into()),
|
||||
("y".try_into().unwrap(), Yank.into()),
|
||||
|
||||
("C- ".try_into().unwrap(), BufferAction::InspectSelection.into()),
|
||||
("A- ".try_into().unwrap(), BufferAction::InspectSelectionColor.into()),
|
||||
("C- ".try_into().unwrap(), InspectSelection.into()),
|
||||
("A- ".try_into().unwrap(), InspectSelectionColor.into()),
|
||||
].into()),
|
||||
(Some(PartialAction::Goto), [
|
||||
("j".try_into().unwrap(), CursorAction::GotoLineStart.into()),
|
||||
("l".try_into().unwrap(), CursorAction::GotoLineEnd.into()),
|
||||
("j".try_into().unwrap(), GotoLineStart.into()),
|
||||
("l".try_into().unwrap(), GotoLineEnd.into()),
|
||||
|
||||
("g".try_into().unwrap(), CursorAction::GotoFileStart.into()),
|
||||
("g".try_into().unwrap(), GotoFileStart.into()),
|
||||
].into()),
|
||||
(Some(PartialAction::View), [
|
||||
("z".try_into().unwrap(), BufferAction::AlignViewCenter.into()),
|
||||
("b".try_into().unwrap(), BufferAction::AlignViewBottom.into()),
|
||||
("t".try_into().unwrap(), BufferAction::AlignViewTop.into()),
|
||||
("z".try_into().unwrap(), AlignViewCenter.into()),
|
||||
("b".try_into().unwrap(), AlignViewBottom.into()),
|
||||
("t".try_into().unwrap(), AlignViewTop.into()),
|
||||
].into()),
|
||||
(Some(PartialAction::Space), [
|
||||
("w".try_into().unwrap(), BufferAction::Save.into()),
|
||||
("w".try_into().unwrap(), Save.into()),
|
||||
].into()),
|
||||
(Some(PartialAction::Repeat), [
|
||||
("i".try_into().unwrap(), CursorAction::MoveByteUp.into()),
|
||||
("k".try_into().unwrap(), CursorAction::MoveByteDown.into()),
|
||||
("j".try_into().unwrap(), CursorAction::MoveByteLeft.into()),
|
||||
("l".try_into().unwrap(), CursorAction::MoveByteRight.into()),
|
||||
("i".try_into().unwrap(), MoveByteUp.into()),
|
||||
("k".try_into().unwrap(), MoveByteDown.into()),
|
||||
("j".try_into().unwrap(), MoveByteLeft.into()),
|
||||
("l".try_into().unwrap(), MoveByteRight.into()),
|
||||
|
||||
("C-e".try_into().unwrap(), BufferAction::ScrollDown.into()),
|
||||
("C-y".try_into().unwrap(), BufferAction::ScrollUp.into()),
|
||||
("C-e".try_into().unwrap(), ScrollDown.into()),
|
||||
("C-y".try_into().unwrap(), ScrollUp.into()),
|
||||
|
||||
("C-d".try_into().unwrap(), BufferAction::PageCursorHalfDown.into()),
|
||||
("C-u".try_into().unwrap(), BufferAction::PageCursorHalfUp.into()),
|
||||
("C-d".try_into().unwrap(), PageCursorHalfDown.into()),
|
||||
("C-u".try_into().unwrap(), PageCursorHalfUp.into()),
|
||||
|
||||
("C-f".try_into().unwrap(), BufferAction::PageDown.into()),
|
||||
("C-b".try_into().unwrap(), BufferAction::PageUp.into()),
|
||||
("C-f".try_into().unwrap(), PageDown.into()),
|
||||
("C-b".try_into().unwrap(), PageUp.into()),
|
||||
|
||||
("w".try_into().unwrap(), CursorAction::MoveNextWordStart.into()),
|
||||
("e".try_into().unwrap(), CursorAction::MoveNextWordEnd.into()),
|
||||
("b".try_into().unwrap(), CursorAction::MovePreviousWordStart.into()),
|
||||
("w".try_into().unwrap(), MoveNextWordStart.into()),
|
||||
("e".try_into().unwrap(), MoveNextWordEnd.into()),
|
||||
("b".try_into().unwrap(), MovePreviousWordStart.into()),
|
||||
|
||||
("x".try_into().unwrap(), CursorAction::ExtendLineBelow.into()),
|
||||
("X".try_into().unwrap(), CursorAction::ExtendLineAbove.into()),
|
||||
("x".try_into().unwrap(), ExtendLineBelow.into()),
|
||||
("X".try_into().unwrap(), ExtendLineAbove.into()),
|
||||
|
||||
("d".try_into().unwrap(), BufferAction::Delete.into()),
|
||||
("d".try_into().unwrap(), Delete.into()),
|
||||
|
||||
("C".try_into().unwrap(), BufferAction::CopySelectionOnNextLine.into()),
|
||||
("C".try_into().unwrap(), CopySelectionOnNextLine.into()),
|
||||
].into()),
|
||||
(Some(PartialAction::To), [
|
||||
("m".try_into().unwrap(), BufferAction::ExtendToMark.into()),
|
||||
("0".try_into().unwrap(), BufferAction::ExtendToNull.into()),
|
||||
("f".try_into().unwrap(), BufferAction::ExtendToFF.into()),
|
||||
("m".try_into().unwrap(), ExtendToMark.into()),
|
||||
("0".try_into().unwrap(), ExtendToNull.into()),
|
||||
("f".try_into().unwrap(), ExtendToFF.into()),
|
||||
].into()),
|
||||
].into()),
|
||||
(Mode::Select, [
|
||||
(None, [
|
||||
("q".try_into().unwrap(), AppAction::QuitIfSaved.into()),
|
||||
("Q".try_into().unwrap(), AppAction::Quit.into()),
|
||||
("q".try_into().unwrap(), QuitIfSaved.into()),
|
||||
("Q".try_into().unwrap(), Quit.into()),
|
||||
|
||||
("v".try_into().unwrap(), BufferAction::NormalMode.into()),
|
||||
("v".try_into().unwrap(), NormalMode.into()),
|
||||
|
||||
("g".try_into().unwrap(), BufferAction::Goto.into()),
|
||||
("z".try_into().unwrap(), BufferAction::View.into()),
|
||||
("r".try_into().unwrap(), BufferAction::Replace.into()),
|
||||
(" ".try_into().unwrap(), BufferAction::Space.into()),
|
||||
("*".try_into().unwrap(), BufferAction::Repeat.into()),
|
||||
("t".try_into().unwrap(), BufferAction::To.into()),
|
||||
("g".try_into().unwrap(), Goto.into()),
|
||||
("z".try_into().unwrap(), View.into()),
|
||||
("r".try_into().unwrap(), Replace.into()),
|
||||
(" ".try_into().unwrap(), Space.into()),
|
||||
("*".try_into().unwrap(), Repeat.into()),
|
||||
("t".try_into().unwrap(), To.into()),
|
||||
|
||||
("i".try_into().unwrap(), CursorAction::ExtendByteUp.into()),
|
||||
("k".try_into().unwrap(), CursorAction::ExtendByteDown.into()),
|
||||
("j".try_into().unwrap(), CursorAction::ExtendByteLeft.into()),
|
||||
("l".try_into().unwrap(), CursorAction::ExtendByteRight.into()),
|
||||
("i".try_into().unwrap(), ExtendByteUp.into()),
|
||||
("k".try_into().unwrap(), ExtendByteDown.into()),
|
||||
("j".try_into().unwrap(), ExtendByteLeft.into()),
|
||||
("l".try_into().unwrap(), ExtendByteRight.into()),
|
||||
|
||||
("C-e".try_into().unwrap(), BufferAction::ScrollDown.into()),
|
||||
("C-y".try_into().unwrap(), BufferAction::ScrollUp.into()),
|
||||
("C-e".try_into().unwrap(), ScrollDown.into()),
|
||||
("C-y".try_into().unwrap(), ScrollUp.into()),
|
||||
|
||||
("C-d".try_into().unwrap(), BufferAction::PageCursorHalfDown.into()),
|
||||
("C-u".try_into().unwrap(), BufferAction::PageCursorHalfUp.into()),
|
||||
("C-d".try_into().unwrap(), PageCursorHalfDown.into()),
|
||||
("C-u".try_into().unwrap(), PageCursorHalfUp.into()),
|
||||
|
||||
("C-f".try_into().unwrap(), BufferAction::PageDown.into()),
|
||||
("C-b".try_into().unwrap(), BufferAction::PageUp.into()),
|
||||
("C-f".try_into().unwrap(), PageDown.into()),
|
||||
("C-b".try_into().unwrap(), PageUp.into()),
|
||||
|
||||
("w".try_into().unwrap(), CursorAction::ExtendNextWordStart.into()),
|
||||
("e".try_into().unwrap(), CursorAction::ExtendNextWordEnd.into()),
|
||||
("b".try_into().unwrap(), CursorAction::ExtendPreviousWordStart.into()),
|
||||
("w".try_into().unwrap(), ExtendNextWordStart.into()),
|
||||
("e".try_into().unwrap(), ExtendNextWordEnd.into()),
|
||||
("b".try_into().unwrap(), ExtendPreviousWordStart.into()),
|
||||
|
||||
(";".try_into().unwrap(), BufferAction::CollapseSelection.into()),
|
||||
("A-;".try_into().unwrap(), BufferAction::FlipSelections.into()),
|
||||
(";".try_into().unwrap(), CollapseSelection.into()),
|
||||
("A-;".try_into().unwrap(), FlipSelections.into()),
|
||||
|
||||
("x".try_into().unwrap(), CursorAction::ExtendLineBelow.into()),
|
||||
("X".try_into().unwrap(), CursorAction::ExtendLineAbove.into()),
|
||||
("x".try_into().unwrap(), ExtendLineBelow.into()),
|
||||
("X".try_into().unwrap(), ExtendLineAbove.into()),
|
||||
|
||||
("d".try_into().unwrap(), BufferAction::Delete.into()),
|
||||
("d".try_into().unwrap(), Delete.into()),
|
||||
|
||||
("u".try_into().unwrap(), BufferAction::Undo.into()),
|
||||
("U".try_into().unwrap(), BufferAction::Redo.into()),
|
||||
("u".try_into().unwrap(), Undo.into()),
|
||||
("U".try_into().unwrap(), Redo.into()),
|
||||
|
||||
("C".try_into().unwrap(), BufferAction::CopySelectionOnNextLine.into()),
|
||||
("C".try_into().unwrap(), CopySelectionOnNextLine.into()),
|
||||
|
||||
("(".try_into().unwrap(), BufferAction::RotateSelectionsBackward.into()),
|
||||
(")".try_into().unwrap(), BufferAction::RotateSelectionsForward.into()),
|
||||
("(".try_into().unwrap(), RotateSelectionsBackward.into()),
|
||||
(")".try_into().unwrap(), RotateSelectionsForward.into()),
|
||||
|
||||
(",".try_into().unwrap(), BufferAction::KeepPrimarySelection.into()),
|
||||
("A-,".try_into().unwrap(), BufferAction::RemovePrimarySelection.into()),
|
||||
(",".try_into().unwrap(), KeepPrimarySelection.into()),
|
||||
("A-,".try_into().unwrap(), RemovePrimarySelection.into()),
|
||||
|
||||
("1".try_into().unwrap(), BufferAction::SplitSelectionsInto1s.into()),
|
||||
("2".try_into().unwrap(), BufferAction::SplitSelectionsInto2s.into()),
|
||||
("3".try_into().unwrap(), BufferAction::SplitSelectionsInto3s.into()),
|
||||
("4".try_into().unwrap(), BufferAction::SplitSelectionsInto4s.into()),
|
||||
("5".try_into().unwrap(), BufferAction::SplitSelectionsInto5s.into()),
|
||||
("6".try_into().unwrap(), BufferAction::SplitSelectionsInto6s.into()),
|
||||
("7".try_into().unwrap(), BufferAction::SplitSelectionsInto7s.into()),
|
||||
("8".try_into().unwrap(), BufferAction::SplitSelectionsInto8s.into()),
|
||||
("9".try_into().unwrap(), BufferAction::SplitSelectionsInto9s.into()),
|
||||
("1".try_into().unwrap(), SplitSelectionsInto1s.into()),
|
||||
("2".try_into().unwrap(), SplitSelectionsInto2s.into()),
|
||||
("3".try_into().unwrap(), SplitSelectionsInto3s.into()),
|
||||
("4".try_into().unwrap(), SplitSelectionsInto4s.into()),
|
||||
("5".try_into().unwrap(), SplitSelectionsInto5s.into()),
|
||||
("6".try_into().unwrap(), SplitSelectionsInto6s.into()),
|
||||
("7".try_into().unwrap(), SplitSelectionsInto7s.into()),
|
||||
("8".try_into().unwrap(), SplitSelectionsInto8s.into()),
|
||||
("9".try_into().unwrap(), SplitSelectionsInto9s.into()),
|
||||
|
||||
("J".try_into().unwrap(), BufferAction::JumpToSelectedOffsetRelativeToMark.into()),
|
||||
("A-J".try_into().unwrap(), BufferAction::JumpToSelectedOffset.into()),
|
||||
("J".try_into().unwrap(), JumpToSelectedOffsetRelativeToMark.into()),
|
||||
("A-J".try_into().unwrap(), JumpToSelectedOffset.into()),
|
||||
|
||||
("m".try_into().unwrap(), BufferAction::ToggleMark.into()),
|
||||
("m".try_into().unwrap(), ToggleMark.into()),
|
||||
|
||||
("y".try_into().unwrap(), AppAction::Yank.into()),
|
||||
("y".try_into().unwrap(), Yank.into()),
|
||||
|
||||
("C- ".try_into().unwrap(), BufferAction::InspectSelection.into()),
|
||||
("A- ".try_into().unwrap(), BufferAction::InspectSelectionColor.into()),
|
||||
("C- ".try_into().unwrap(), InspectSelection.into()),
|
||||
("A- ".try_into().unwrap(), InspectSelectionColor.into()),
|
||||
].into()),
|
||||
(Some(PartialAction::View), [
|
||||
("z".try_into().unwrap(), BufferAction::AlignViewCenter.into()),
|
||||
("b".try_into().unwrap(), BufferAction::AlignViewBottom.into()),
|
||||
("t".try_into().unwrap(), BufferAction::AlignViewTop.into()),
|
||||
("z".try_into().unwrap(), AlignViewCenter.into()),
|
||||
("b".try_into().unwrap(), AlignViewBottom.into()),
|
||||
("t".try_into().unwrap(), AlignViewTop.into()),
|
||||
].into()),
|
||||
(Some(PartialAction::Space), [
|
||||
("w".try_into().unwrap(), BufferAction::Save.into()),
|
||||
("w".try_into().unwrap(), Save.into()),
|
||||
].into()),
|
||||
(Some(PartialAction::Repeat), [
|
||||
("i".try_into().unwrap(), CursorAction::ExtendByteUp.into()),
|
||||
("k".try_into().unwrap(), CursorAction::ExtendByteDown.into()),
|
||||
("j".try_into().unwrap(), CursorAction::ExtendByteLeft.into()),
|
||||
("l".try_into().unwrap(), CursorAction::ExtendByteRight.into()),
|
||||
("i".try_into().unwrap(), ExtendByteUp.into()),
|
||||
("k".try_into().unwrap(), ExtendByteDown.into()),
|
||||
("j".try_into().unwrap(), ExtendByteLeft.into()),
|
||||
("l".try_into().unwrap(), ExtendByteRight.into()),
|
||||
|
||||
("C-e".try_into().unwrap(), BufferAction::ScrollDown.into()),
|
||||
("C-y".try_into().unwrap(), BufferAction::ScrollUp.into()),
|
||||
("C-e".try_into().unwrap(), ScrollDown.into()),
|
||||
("C-y".try_into().unwrap(), ScrollUp.into()),
|
||||
|
||||
("C-d".try_into().unwrap(), BufferAction::PageCursorHalfDown.into()),
|
||||
("C-u".try_into().unwrap(), BufferAction::PageCursorHalfUp.into()),
|
||||
("C-d".try_into().unwrap(), PageCursorHalfDown.into()),
|
||||
("C-u".try_into().unwrap(), PageCursorHalfUp.into()),
|
||||
|
||||
("C-f".try_into().unwrap(), BufferAction::PageDown.into()),
|
||||
("C-b".try_into().unwrap(), BufferAction::PageUp.into()),
|
||||
("C-f".try_into().unwrap(), PageDown.into()),
|
||||
("C-b".try_into().unwrap(), PageUp.into()),
|
||||
|
||||
("w".try_into().unwrap(), CursorAction::ExtendNextWordStart.into()),
|
||||
("e".try_into().unwrap(), CursorAction::ExtendNextWordEnd.into()),
|
||||
("b".try_into().unwrap(), CursorAction::ExtendPreviousWordStart.into()),
|
||||
("w".try_into().unwrap(), ExtendNextWordStart.into()),
|
||||
("e".try_into().unwrap(), ExtendNextWordEnd.into()),
|
||||
("b".try_into().unwrap(), ExtendPreviousWordStart.into()),
|
||||
|
||||
("x".try_into().unwrap(), CursorAction::ExtendLineBelow.into()),
|
||||
("X".try_into().unwrap(), CursorAction::ExtendLineAbove.into()),
|
||||
("x".try_into().unwrap(), ExtendLineBelow.into()),
|
||||
("X".try_into().unwrap(), ExtendLineAbove.into()),
|
||||
|
||||
("d".try_into().unwrap(), BufferAction::Delete.into()),
|
||||
("d".try_into().unwrap(), Delete.into()),
|
||||
|
||||
("C".try_into().unwrap(), BufferAction::CopySelectionOnNextLine.into()),
|
||||
("C".try_into().unwrap(), CopySelectionOnNextLine.into()),
|
||||
].into()),
|
||||
(Some(PartialAction::To), [
|
||||
("m".try_into().unwrap(), BufferAction::ExtendToMark.into()),
|
||||
("0".try_into().unwrap(), BufferAction::ExtendToNull.into()),
|
||||
("f".try_into().unwrap(), BufferAction::ExtendToFF.into()),
|
||||
("m".try_into().unwrap(), ExtendToMark.into()),
|
||||
("0".try_into().unwrap(), ExtendToNull.into()),
|
||||
("f".try_into().unwrap(), ExtendToFF.into()),
|
||||
].into()),
|
||||
].into())
|
||||
].into()
|
||||
|
||||
+14
@@ -5,9 +5,13 @@
|
||||
#![feature(hash_set_entry)]
|
||||
#![feature(trim_prefix_suffix)]
|
||||
|
||||
use std::fs::read_to_string;
|
||||
|
||||
use app::App;
|
||||
use crossterm::{QueueableCommand, event::{DisableMouseCapture, EnableMouseCapture}};
|
||||
|
||||
use crate::config::Config;
|
||||
|
||||
mod app;
|
||||
mod buffer;
|
||||
mod config;
|
||||
@@ -55,6 +59,16 @@ const BYTES_OF_PADDING: usize = LINES_OF_PADDING * BYTES_PER_LINE;
|
||||
// - how to fit??! `-128` longer than `80`
|
||||
|
||||
fn main() {
|
||||
// let config = Config::default();
|
||||
// let toml_string = toml::to_string_pretty(&config);
|
||||
// println!("{}", toml_string.unwrap());
|
||||
|
||||
// let string = read_to_string("/Users/simonomi/Desktop/hexapoda_config.toml").unwrap();
|
||||
// let config: Config = toml::from_str(&string).unwrap();
|
||||
// dbg!(config.0);
|
||||
|
||||
// return;
|
||||
|
||||
let mut app = App::new();
|
||||
let mut terminal = ratatui::init();
|
||||
crossterm::terminal::enable_raw_mode().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user