use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
#[non_exhaustive]
pub enum KeyGroup {
Global,
Editor,
Sidebar,
Results,
RowDetail,
CellPopup,
JsonViewer,
PendingPreview,
}
impl KeyGroup {
pub const fn as_str(self) -> &'static str {
match self {
Self::Global => "global",
Self::Editor => "editor",
Self::Sidebar => "sidebar",
Self::Results => "results",
Self::RowDetail => "row-detail",
Self::CellPopup => "cell-popup",
Self::JsonViewer => "json-viewer",
Self::PendingPreview => "pending-preview",
}
}
pub fn from_str_opt(s: &str) -> Option<Self> {
match s {
"global" => Some(Self::Global),
"editor" => Some(Self::Editor),
"sidebar" => Some(Self::Sidebar),
"results" => Some(Self::Results),
"row-detail" | "row_detail" => Some(Self::RowDetail),
"cell-popup" | "cell_popup" => Some(Self::CellPopup),
"json-viewer" | "json_viewer" => Some(Self::JsonViewer),
"pending-preview" | "pending_preview" => Some(Self::PendingPreview),
_ => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
#[non_exhaustive]
pub enum Action {
ResultsMoveDown,
ResultsMoveUp,
ResultsMoveLeft,
ResultsMoveRight,
ResultsFirstRow,
ResultsLastRow,
ResultsToggleSort,
ResultsOpenFilterPrompt,
ResultsNextMatch,
ResultsPrevMatch,
ResultsEscape,
ResultsOpenCellPopup,
ResultsOpenRowDetail,
ResultsStartCellEdit,
ResultsYankCell,
ResultsYankRow,
ResultsNextStatementLeader,
ResultsPrevStatementLeader,
ResultsAppendRow,
ResultsDuplicateRow,
ResultsDeleteRow,
ResultsCommitPending,
ResultsDiscardPending,
ResultsOpenPendingPreview,
MetaTabRecords,
MetaTabColumns,
MetaTabConstraints,
MetaTabForeignKeys,
MetaTabIndexes,
OpenJsonViewerCell,
OpenJsonViewerRow,
ResultsFkGotoDefinition,
}
impl Action {
pub const fn default_group(self) -> KeyGroup {
match self {
Self::ResultsMoveDown
| Self::ResultsMoveUp
| Self::ResultsMoveLeft
| Self::ResultsMoveRight
| Self::ResultsFirstRow
| Self::ResultsLastRow
| Self::ResultsToggleSort
| Self::ResultsOpenFilterPrompt
| Self::ResultsNextMatch
| Self::ResultsPrevMatch
| Self::ResultsEscape
| Self::ResultsOpenCellPopup
| Self::ResultsOpenRowDetail
| Self::ResultsStartCellEdit
| Self::ResultsYankCell
| Self::ResultsYankRow
| Self::ResultsNextStatementLeader
| Self::ResultsPrevStatementLeader
| Self::ResultsAppendRow
| Self::ResultsDuplicateRow
| Self::ResultsDeleteRow
| Self::ResultsCommitPending
| Self::ResultsDiscardPending
| Self::ResultsOpenPendingPreview
| Self::MetaTabRecords
| Self::MetaTabColumns
| Self::MetaTabConstraints
| Self::MetaTabForeignKeys
| Self::MetaTabIndexes
| Self::OpenJsonViewerCell
| Self::ResultsFkGotoDefinition => KeyGroup::Results,
Self::OpenJsonViewerRow => KeyGroup::RowDetail,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn key_group_roundtrip() {
for group in [
KeyGroup::Global,
KeyGroup::Editor,
KeyGroup::Sidebar,
KeyGroup::Results,
KeyGroup::RowDetail,
KeyGroup::CellPopup,
KeyGroup::JsonViewer,
KeyGroup::PendingPreview,
] {
assert_eq!(KeyGroup::from_str_opt(group.as_str()), Some(group));
}
}
#[test]
fn key_group_accepts_snake_alias() {
assert_eq!(
KeyGroup::from_str_opt("row_detail"),
Some(KeyGroup::RowDetail)
);
assert_eq!(
KeyGroup::from_str_opt("pending_preview"),
Some(KeyGroup::PendingPreview)
);
}
#[test]
fn action_serde_uses_kebab_case() {
let s = serde_json::to_string(&Action::ResultsAppendRow).unwrap();
assert_eq!(s, "\"results-append-row\"");
let back: Action = serde_json::from_str("\"results-append-row\"").unwrap();
assert_eq!(back, Action::ResultsAppendRow);
}
#[test]
fn default_group_routes_actions_correctly() {
assert_eq!(Action::ResultsMoveDown.default_group(), KeyGroup::Results);
assert_eq!(
Action::OpenJsonViewerRow.default_group(),
KeyGroup::RowDetail
);
assert_eq!(Action::MetaTabRecords.default_group(), KeyGroup::Results);
}
}