Files
hexapoda/src/action.rs
T
2026-04-25 22:17:44 -05:00

594 lines
13 KiB
Rust

use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Serialize, Deserialize)]
#[derive(Debug)]
#[serde(into = "&str")]
#[serde(try_from = "&str")]
pub enum Action {
App(AppAction),
Buffer(BufferAction),
Cursor(CursorAction),
}
impl Action {
pub const fn clears_popups(self) -> bool {
use Action::*;
match self {
App(app_action) => app_action.clears_popups(),
Buffer(buffer_action) => buffer_action.clears_popups(),
Cursor(cursor_action) => cursor_action.clears_popups(),
}
}
pub const fn is_inspection(self) -> bool {
use Action::*;
use BufferAction::*;
matches!(self, Buffer(InspectSelection | InspectSelectionColor))
}
}
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(Self::from)
.or_else(|()| BufferAction::try_from(string).map(Self::from))
.or_else(|()| CursorAction::try_from(string).map(Self::from))
.map_err(|()| format!("invalid action: {string}"))
}
}
// actions that act on the app as a whole, not just one buffer
#[derive(Debug, Clone, Copy, Deserialize)]
pub enum AppAction {
QuitIfSaved,
Quit,
PreviousBuffer,
NextBuffer,
Yank,
}
impl AppAction {
const fn clears_popups(self) -> bool {
use AppAction::*;
#[allow(clippy::match_same_arms)]
match self {
QuitIfSaved => true,
Quit => true,
PreviousBuffer => false,
NextBuffer => false,
Yank => false,
}
}
}
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)
}
}
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,
Goto,
View,
Replace,
Space,
Repeat,
To,
ScrollDown,
ScrollUp,
PageCursorHalfDown,
PageCursorHalfUp,
PageDown,
PageUp,
CollapseSelection,
FlipSelections,
Delete,
Undo,
Redo,
Save,
CopySelectionOnNextLine,
RotateSelectionsBackward,
RotateSelectionsForward,
KeepPrimarySelection,
RemovePrimarySelection,
SplitSelectionsInto1s,
SplitSelectionsInto2s,
SplitSelectionsInto3s,
SplitSelectionsInto4s,
SplitSelectionsInto5s,
SplitSelectionsInto6s,
SplitSelectionsInto7s,
SplitSelectionsInto8s,
SplitSelectionsInto9s,
JumpToSelectedOffset,
JumpToSelectedOffsetRelativeToMark,
ToggleMark,
AlignViewCenter,
AlignViewBottom,
AlignViewTop,
FindTillMark,
FindTillNull,
FindTillFF,
ExtendTillMark,
ExtendTillNull,
ExtendTillFF,
InspectSelection,
InspectSelectionColor,
}
impl BufferAction {
const fn clears_popups(self) -> bool {
use BufferAction::*;
#[allow(clippy::match_same_arms)]
match self {
NormalMode => false,
SelectMode => false,
Goto => false,
View => false,
Replace => true,
Space => false,
Repeat => true,
To => false,
ScrollDown => true,
ScrollUp => true,
PageCursorHalfDown => true,
PageCursorHalfUp => true,
PageDown => true,
PageUp => true,
CollapseSelection => true,
FlipSelections => false,
Delete => true,
Undo => true,
Redo => true,
Save => false,
CopySelectionOnNextLine => true,
RotateSelectionsBackward => false,
RotateSelectionsForward => false,
KeepPrimarySelection => true,
RemovePrimarySelection => true,
SplitSelectionsInto1s => true,
SplitSelectionsInto2s => true,
SplitSelectionsInto3s => true,
SplitSelectionsInto4s => true,
SplitSelectionsInto5s => true,
SplitSelectionsInto6s => true,
SplitSelectionsInto7s => true,
SplitSelectionsInto8s => true,
SplitSelectionsInto9s => true,
JumpToSelectedOffset => true,
JumpToSelectedOffsetRelativeToMark => true,
ToggleMark => false,
AlignViewCenter => false,
AlignViewBottom => false,
AlignViewTop => false,
FindTillMark => true,
FindTillNull => true,
FindTillFF => true,
ExtendTillMark => true,
ExtendTillNull => true,
ExtendTillFF => true,
InspectSelection => true,
InspectSelectionColor => true,
}
}
}
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_1s",
SplitSelectionsInto2s => "split_selections_into_2s",
SplitSelectionsInto3s => "split_selections_into_3s",
SplitSelectionsInto4s => "split_selections_into_4s",
SplitSelectionsInto5s => "split_selections_into_5s",
SplitSelectionsInto6s => "split_selections_into_6s",
SplitSelectionsInto7s => "split_selections_into_7s",
SplitSelectionsInto8s => "split_selections_into_8s",
SplitSelectionsInto9s => "split_selections_into_9s",
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",
FindTillMark => "find_till_mark",
FindTillNull => "find_till_null",
FindTillFF => "find_till_ff",
ExtendTillMark => "extend_till_mark",
ExtendTillNull => "extend_till_null",
ExtendTillFF => "extend_till_ff",
InspectSelection => "inspect_selection",
InspectSelectionColor => "inspect_selection_color",
}
}
}
impl From<BufferAction> for Action {
fn from(buffer_action: BufferAction) -> Self {
Self::Buffer(buffer_action)
}
}
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_1s" => Ok(SplitSelectionsInto1s),
"split_selections_into_2s" => Ok(SplitSelectionsInto2s),
"split_selections_into_3s" => Ok(SplitSelectionsInto3s),
"split_selections_into_4s" => Ok(SplitSelectionsInto4s),
"split_selections_into_5s" => Ok(SplitSelectionsInto5s),
"split_selections_into_6s" => Ok(SplitSelectionsInto6s),
"split_selections_into_7s" => Ok(SplitSelectionsInto7s),
"split_selections_into_8s" => Ok(SplitSelectionsInto8s),
"split_selections_into_9s" => 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),
"find_till_mark" => Ok(FindTillMark),
"find_till_null" => Ok(FindTillNull),
"find_till_ff" => Ok(FindTillFF),
"extend_till_mark" => Ok(ExtendTillMark),
"extend_till_null" => Ok(ExtendTillNull),
"extend_till_ff" => Ok(ExtendTillFF),
"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,
MoveByteLeft,
MoveByteRight,
ExtendByteUp,
ExtendByteDown,
ExtendByteLeft,
ExtendByteRight,
GotoLineStart,
GotoLineEnd,
GotoFileStart,
GotoFileEnd,
ExtendLineStart,
ExtendLineEnd,
ExtendFileStart,
ExtendFileEnd,
MoveNextWordStart,
MoveNextWordEnd,
MovePreviousWordStart,
ExtendNextWordStart,
ExtendNextWordEnd,
ExtendPreviousWordStart,
ExtendLineBelow,
ExtendLineAbove,
}
impl CursorAction {
const fn clears_popups(self) -> bool {
use CursorAction::*;
#[allow(clippy::match_same_arms)]
match self {
MoveByteUp => true,
MoveByteDown => true,
MoveByteLeft => true,
MoveByteRight => true,
ExtendByteUp => true,
ExtendByteDown => true,
ExtendByteLeft => true,
ExtendByteRight => true,
GotoLineStart => true,
GotoLineEnd => true,
GotoFileStart => true,
GotoFileEnd => true,
ExtendLineStart => true,
ExtendLineEnd => true,
ExtendFileStart => true,
ExtendFileEnd => true,
MoveNextWordStart => true,
MoveNextWordEnd => true,
MovePreviousWordStart => true,
ExtendNextWordStart => true,
ExtendNextWordEnd => true,
ExtendPreviousWordStart => true,
ExtendLineBelow => true,
ExtendLineAbove => true,
}
}
}
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",
ExtendLineStart => "extend_line_start",
ExtendLineEnd => "extend_line_end",
ExtendFileStart => "extend_file_start",
ExtendFileEnd => "extend_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),
"extend_line_start" => Ok(ExtendLineStart),
"extend_line_end" => Ok(ExtendLineEnd),
"extend_file_start" => Ok(ExtendFileStart),
"extend_file_end" => Ok(ExtendFileEnd),
"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(()),
}
}
}