use std::collections::HashSet;
use promkit_widgets::{
core::crossterm::{
event::{KeyCode, KeyModifiers},
style::{Attribute, Attributes, Color, ContentStyle},
},
text_editor::Mode,
};
use serde::{Deserialize, Serialize};
use tokio::time::Duration;
mod content_style;
use content_style::content_style_serde;
mod duration;
use duration::duration_serde;
pub mod event;
use event::{EventDef, EventDefSet, KeyEventDef};
mod text_editor;
use text_editor::text_editor_mode_serde;
#[derive(Serialize, Deserialize)]
pub struct EditorConfig {
pub theme_on_focus: EditorTheme,
pub theme_on_defocus: EditorTheme,
#[serde(with = "text_editor_mode_serde")]
pub mode: Mode,
pub word_break_chars: HashSet<char>,
}
#[derive(Serialize, Deserialize)]
pub struct EditorTheme {
pub prefix: String,
#[serde(with = "content_style_serde")]
pub prefix_style: ContentStyle,
#[serde(with = "content_style_serde")]
pub active_char_style: ContentStyle,
#[serde(with = "content_style_serde")]
pub inactive_char_style: ContentStyle,
}
impl Default for EditorConfig {
fn default() -> Self {
Self {
theme_on_focus: EditorTheme {
prefix: String::from("❯❯ "),
prefix_style: ContentStyle {
foreground_color: Some(Color::Blue),
..Default::default()
},
active_char_style: ContentStyle {
background_color: Some(Color::Magenta),
..Default::default()
},
inactive_char_style: ContentStyle::default(),
},
theme_on_defocus: EditorTheme {
prefix: String::from("▼ "),
prefix_style: ContentStyle {
foreground_color: Some(Color::Blue),
attributes: Attributes::from(Attribute::Dim),
..Default::default()
},
active_char_style: ContentStyle {
attributes: Attributes::from(Attribute::Dim),
..Default::default()
},
inactive_char_style: ContentStyle {
attributes: Attributes::from(Attribute::Dim),
..Default::default()
},
},
mode: Mode::Insert,
word_break_chars: HashSet::from(['.', '|', '(', ')', '[', ']']),
}
}
}
#[derive(Serialize, Deserialize)]
pub struct JsonConfig {
pub max_streams: Option<usize>,
pub theme: JsonTheme,
}
#[derive(Serialize, Deserialize)]
pub struct JsonTheme {
pub indent: usize,
#[serde(with = "content_style_serde")]
pub curly_brackets_style: ContentStyle,
#[serde(with = "content_style_serde")]
pub square_brackets_style: ContentStyle,
#[serde(with = "content_style_serde")]
pub key_style: ContentStyle,
#[serde(with = "content_style_serde")]
pub string_value_style: ContentStyle,
#[serde(with = "content_style_serde")]
pub number_value_style: ContentStyle,
#[serde(with = "content_style_serde")]
pub boolean_value_style: ContentStyle,
#[serde(with = "content_style_serde")]
pub null_value_style: ContentStyle,
}
impl Default for JsonConfig {
fn default() -> Self {
Self {
max_streams: None,
theme: JsonTheme {
indent: 2,
curly_brackets_style: ContentStyle {
attributes: Attributes::from(Attribute::Bold),
..Default::default()
},
square_brackets_style: ContentStyle {
attributes: Attributes::from(Attribute::Bold),
..Default::default()
},
key_style: ContentStyle {
foreground_color: Some(Color::Cyan),
..Default::default()
},
string_value_style: ContentStyle {
foreground_color: Some(Color::Green),
..Default::default()
},
number_value_style: ContentStyle::default(),
boolean_value_style: ContentStyle::default(),
null_value_style: ContentStyle {
foreground_color: Some(Color::Grey),
..Default::default()
},
},
}
}
}
#[derive(Serialize, Deserialize)]
pub struct CompletionConfig {
pub lines: Option<usize>,
pub cursor: String,
pub search_result_chunk_size: usize,
pub search_load_chunk_size: usize,
#[serde(with = "content_style_serde")]
pub active_item_style: ContentStyle,
#[serde(with = "content_style_serde")]
pub inactive_item_style: ContentStyle,
}
impl Default for CompletionConfig {
fn default() -> Self {
Self {
lines: Some(3),
cursor: String::from("❯ "),
search_result_chunk_size: 100,
search_load_chunk_size: 50000,
active_item_style: ContentStyle {
foreground_color: Some(Color::Grey),
background_color: Some(Color::Yellow),
..Default::default()
},
inactive_item_style: ContentStyle {
foreground_color: Some(Color::Grey),
..Default::default()
},
}
}
}
#[derive(Clone, Serialize, Deserialize)]
pub struct Keybinds {
pub exit: EventDefSet,
pub copy_query: EventDefSet,
pub copy_result: EventDefSet,
pub switch_mode: EventDefSet,
pub on_editor: EditorKeybinds,
pub on_json_viewer: JsonViewerKeybinds,
}
#[derive(Clone, Serialize, Deserialize)]
pub struct EditorKeybinds {
pub backward: EventDefSet,
pub forward: EventDefSet,
pub move_to_head: EventDefSet,
pub move_to_tail: EventDefSet,
pub move_to_previous_nearest: EventDefSet,
pub move_to_next_nearest: EventDefSet,
pub erase: EventDefSet,
pub erase_all: EventDefSet,
pub erase_to_previous_nearest: EventDefSet,
pub erase_to_next_nearest: EventDefSet,
pub completion: EventDefSet,
pub on_completion: CompletionKeybinds,
}
#[derive(Clone, Serialize, Deserialize)]
pub struct CompletionKeybinds {
pub up: EventDefSet,
pub down: EventDefSet,
}
#[derive(Clone, Serialize, Deserialize)]
pub struct JsonViewerKeybinds {
pub up: EventDefSet,
pub down: EventDefSet,
pub move_to_head: EventDefSet,
pub move_to_tail: EventDefSet,
pub toggle: EventDefSet,
pub expand: EventDefSet,
pub collapse: EventDefSet,
}
impl Default for Keybinds {
fn default() -> Self {
Self {
exit: EventDefSet::from(KeyEventDef::new(KeyCode::Char('c'), KeyModifiers::CONTROL)),
copy_query: EventDefSet::from(KeyEventDef::new(
KeyCode::Char('q'),
KeyModifiers::CONTROL,
)),
copy_result: EventDefSet::from(KeyEventDef::new(
KeyCode::Char('o'),
KeyModifiers::CONTROL,
)),
switch_mode: EventDefSet::from_iter([
EventDef::Key(KeyEventDef::new(KeyCode::Down, KeyModifiers::SHIFT)),
EventDef::Key(KeyEventDef::new(KeyCode::Up, KeyModifiers::SHIFT)),
]),
on_editor: EditorKeybinds {
backward: EventDefSet::from(KeyEventDef::new(KeyCode::Left, KeyModifiers::NONE)),
forward: EventDefSet::from(KeyEventDef::new(KeyCode::Right, KeyModifiers::NONE)),
move_to_head: EventDefSet::from(KeyEventDef::new(
KeyCode::Char('a'),
KeyModifiers::CONTROL,
)),
move_to_tail: EventDefSet::from(KeyEventDef::new(
KeyCode::Char('e'),
KeyModifiers::CONTROL,
)),
move_to_next_nearest: EventDefSet::from(KeyEventDef::new(
KeyCode::Char('f'),
KeyModifiers::ALT,
)),
move_to_previous_nearest: EventDefSet::from(KeyEventDef::new(
KeyCode::Char('b'),
KeyModifiers::ALT,
)),
erase: EventDefSet::from(KeyEventDef::new(KeyCode::Backspace, KeyModifiers::NONE)),
erase_all: EventDefSet::from(KeyEventDef::new(
KeyCode::Char('u'),
KeyModifiers::CONTROL,
)),
erase_to_previous_nearest: EventDefSet::from(KeyEventDef::new(
KeyCode::Char('w'),
KeyModifiers::CONTROL,
)),
erase_to_next_nearest: EventDefSet::from(KeyEventDef::new(
KeyCode::Char('d'),
KeyModifiers::ALT,
)),
completion: EventDefSet::from(KeyEventDef::new(KeyCode::Tab, KeyModifiers::NONE)),
on_completion: CompletionKeybinds {
up: EventDefSet::from(KeyEventDef::new(KeyCode::Up, KeyModifiers::NONE)),
down: EventDefSet::from_iter([
EventDef::Key(KeyEventDef::new(KeyCode::Tab, KeyModifiers::NONE)),
EventDef::Key(KeyEventDef::new(KeyCode::Down, KeyModifiers::NONE)),
]),
},
},
on_json_viewer: JsonViewerKeybinds {
up: EventDefSet::from_iter([
EventDef::Key(KeyEventDef::new(KeyCode::Char('k'), KeyModifiers::CONTROL)),
EventDef::Key(KeyEventDef::new(KeyCode::Up, KeyModifiers::NONE)),
]),
down: EventDefSet::from_iter([
EventDef::Key(KeyEventDef::new(KeyCode::Char('j'), KeyModifiers::CONTROL)),
EventDef::Key(KeyEventDef::new(KeyCode::Down, KeyModifiers::NONE)),
]),
move_to_head: EventDefSet::from(KeyEventDef::new(
KeyCode::Char('l'),
KeyModifiers::CONTROL,
)),
move_to_tail: EventDefSet::from(KeyEventDef::new(
KeyCode::Char('h'),
KeyModifiers::CONTROL,
)),
toggle: EventDefSet::from(KeyEventDef::new(KeyCode::Enter, KeyModifiers::NONE)),
expand: EventDefSet::from(KeyEventDef::new(
KeyCode::Char('p'),
KeyModifiers::CONTROL,
)),
collapse: EventDefSet::from(KeyEventDef::new(
KeyCode::Char('n'),
KeyModifiers::CONTROL,
)),
},
}
}
}
#[derive(Serialize, Deserialize)]
pub struct ReactivityControl {
#[serde(with = "duration_serde")]
pub query_debounce_duration: Duration,
#[serde(with = "duration_serde")]
pub resize_debounce_duration: Duration,
#[serde(with = "duration_serde")]
pub spin_duration: Duration,
}
impl Default for ReactivityControl {
fn default() -> Self {
Self {
query_debounce_duration: Duration::from_millis(600),
resize_debounce_duration: Duration::from_millis(200),
spin_duration: Duration::from_millis(300),
}
}
}
#[derive(Default, Serialize, Deserialize)]
pub struct Config {
pub no_hint: bool,
pub reactivity_control: ReactivityControl,
pub editor: EditorConfig,
pub json: JsonConfig,
pub completion: CompletionConfig,
pub keybinds: Keybinds,
}
impl Config {
pub fn load_from(content: &str) -> anyhow::Result<Self> {
toml::from_str(content).map_err(Into::into)
}
}