implement key config

pull/33/head
Takayuki Maeda 3 years ago
parent 3c00d78326
commit b84cdc1cb1

@ -8,7 +8,7 @@ use crate::{
ConnectionsComponent, DatabasesComponent, ErrorComponent, HelpComponent,
RecordTableComponent, TabComponent, TableComponent, TableStatusComponent,
},
user_config::UserConfig,
config::Config,
};
use database_tree::Database;
use tui::{
@ -33,38 +33,27 @@ pub struct App {
table_status: TableStatusComponent,
clipboard: Clipboard,
pool: Option<Box<dyn Pool>>,
pub user_config: Option<UserConfig>,
pub config: Config,
pub error: ErrorComponent,
}
impl Default for App {
fn default() -> App {
App {
impl App {
pub fn new(config: Config) -> App {
Self {
focus: Focus::ConnectionList,
config: config.clone(),
connections: ConnectionsComponent::new(config.conn),
record_table: RecordTableComponent::default(),
structure_table: TableComponent::default(),
focus: Focus::DabataseList,
tab: TabComponent::default(),
help: HelpComponent::new(),
user_config: None,
help: HelpComponent::new(config.key_config),
databases: DatabasesComponent::new(),
connections: ConnectionsComponent::default(),
table_status: TableStatusComponent::default(),
clipboard: Clipboard::new(),
pool: None,
error: ErrorComponent::default(),
}
}
}
impl App {
pub fn new(user_config: UserConfig) -> App {
Self {
user_config: Some(user_config.clone()),
connections: ConnectionsComponent::new(user_config.conn),
focus: Focus::ConnectionList,
..App::default()
}
}
pub fn draw<B: Backend>(&mut self, f: &mut Frame<'_, B>) -> anyhow::Result<()> {
if let Focus::ConnectionList = self.focus {
@ -140,7 +129,7 @@ impl App {
pub async fn event(&mut self, key: Key) -> anyhow::Result<EventState> {
self.update_commands();
if let Key::Esc = key {
if key == self.config.key_config.exit_popup {
if self.error.error.is_some() {
self.error.error = None;
return Ok(EventState::Consumed);
@ -168,7 +157,7 @@ impl App {
return Ok(EventState::Consumed);
}
if let Key::Enter = key {
if key == self.config.key_config.enter {
self.record_table.reset();
if let Some(conn) = self.connections.selected_connection() {
if let Some(pool) = self.pool.as_ref() {
@ -199,7 +188,7 @@ impl App {
return Ok(EventState::Consumed);
}
if matches!(key, Key::Enter) && self.databases.tree_focused() {
if key == self.config.key_config.enter && self.databases.tree_focused() {
if let Some((table, database)) = self.databases.tree().selected_table() {
self.focus = Focus::Table;
let (headers, records) = self
@ -231,13 +220,14 @@ impl App {
return Ok(EventState::Consumed);
};
if let Key::Char('y') = key {
if key == self.config.key_config.copy {
if let Some(text) = self.record_table.table.selected_cells() {
self.clipboard.store(text)
}
}
if matches!(key, Key::Enter) && self.record_table.filter_focused() {
if key == self.config.key_config.enter && self.record_table.filter_focused()
{
self.record_table.focus = crate::components::record_table::Focus::Table;
if let Some((table, database)) = self.databases.tree().selected_table()
{
@ -301,7 +291,7 @@ impl App {
return Ok(EventState::Consumed);
};
if let Key::Char('y') = key {
if key == self.config.key_config.copy {
if let Some(text) = self.structure_table.selected_cells() {
self.clipboard.store(text)
}
@ -323,19 +313,19 @@ impl App {
}
match self.focus {
Focus::ConnectionList => {
if let Key::Enter = key {
if key == self.config.key_config.enter {
self.focus = Focus::DabataseList;
return Ok(EventState::Consumed);
}
}
Focus::DabataseList => {
if matches!(key, Key::Right) && self.databases.tree_focused() {
if key == self.config.key_config.focus_right && self.databases.tree_focused() {
self.focus = Focus::Table;
return Ok(EventState::Consumed);
}
}
Focus::Table => {
if let Key::Left = key {
if key == self.config.key_config.focus_left {
self.focus = Focus::DabataseList;
return Ok(EventState::Consumed);
}

@ -1,7 +1,7 @@
use super::{Component, DrawableComponent, EventState};
use crate::components::command::CommandInfo;
use crate::config::Connection;
use crate::event::Key;
use crate::user_config::Connection;
use anyhow::Result;
use tui::{
backend::Backend,

@ -0,0 +1,107 @@
use crate::Key;
use serde::Deserialize;
use std::fs::File;
use std::io::{BufReader, Read};
#[derive(Debug, Deserialize, Clone)]
pub struct Config {
pub conn: Vec<Connection>,
#[serde(default)]
pub key_config: KeyConfig,
}
impl Default for Config {
fn default() -> Self {
Self {
conn: vec![Connection {
name: None,
user: "root".to_string(),
host: "localhost".to_string(),
port: 3306,
database: None,
}],
key_config: KeyConfig::default(),
}
}
}
#[derive(Debug, Deserialize, Clone)]
pub struct Connection {
name: Option<String>,
user: String,
host: String,
port: u64,
pub database: Option<String>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct KeyConfig {
pub move_up: Key,
pub move_down: Key,
pub move_right: Key,
pub move_left: Key,
pub copy: Key,
pub enter: Key,
pub exit: Key,
pub quit: Key,
pub exit_popup: Key,
pub focus_right: Key,
pub focus_left: Key,
pub open_help: Key,
}
impl Default for KeyConfig {
fn default() -> Self {
Self {
move_up: Key::Char('k'),
move_down: Key::Char('j'),
move_right: Key::Char('l'),
move_left: Key::Char('h'),
copy: Key::Char('y'),
enter: Key::Enter,
exit: Key::Ctrl('c'),
quit: Key::Char('q'),
exit_popup: Key::Esc,
focus_right: Key::Right,
focus_left: Key::Left,
open_help: Key::Char('?'),
}
}
}
impl Config {
pub fn new(path: &str) -> anyhow::Result<Self> {
if let Ok(file) = File::open(path) {
let mut buf_reader = BufReader::new(file);
let mut contents = String::new();
buf_reader.read_to_string(&mut contents)?;
let config: Result<Config, toml::de::Error> = toml::from_str(&contents);
match config {
Ok(config) => return Ok(config),
Err(e) => panic!("fail to parse config file: {}", e),
}
}
Ok(Config::default())
}
}
impl Connection {
pub fn database_url(&self) -> String {
match &self.database {
Some(database) => format!(
"mysql://{user}:@{host}:{port}/{database}",
user = self.user,
host = self.host,
port = self.port,
database = database
),
None => format!(
"mysql://{user}:@{host}:{port}",
user = self.user,
host = self.host,
port = self.port,
),
}
}
}

@ -1,8 +1,9 @@
use crossterm::event;
use serde::Deserialize;
use std::fmt;
/// Represents a key.
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug, Deserialize)]
pub enum Key {
/// Both Enter (or Return) and numpad Enter
Enter,

@ -1,9 +1,9 @@
mod app;
mod clipboard;
mod components;
mod config;
mod event;
mod ui;
mod user_config;
mod utils;
#[macro_use]
@ -28,7 +28,7 @@ async fn main() -> anyhow::Result<()> {
outln!("gobang logger");
let user_config = user_config::UserConfig::new("sample.toml").ok();
let config = config::Config::new("sample.toml")?;
let stdout = stdout();
setup_terminal()?;
@ -36,7 +36,7 @@ async fn main() -> anyhow::Result<()> {
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
let events = event::Events::new(250);
let mut app = App::new(user_config.unwrap());
let mut app = App::new(config);
terminal.clear()?;

@ -1,52 +0,0 @@
use serde::Deserialize;
use std::fs::File;
use std::io::{BufReader, Read};
#[derive(Debug, Deserialize, Clone)]
pub struct UserConfig {
pub conn: Vec<Connection>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct Connection {
name: Option<String>,
user: String,
host: String,
port: u64,
pub database: Option<String>,
}
impl UserConfig {
pub fn new(path: &str) -> anyhow::Result<Self> {
let file = File::open(path)?;
let mut buf_reader = BufReader::new(file);
let mut contents = String::new();
buf_reader.read_to_string(&mut contents)?;
let config: Result<UserConfig, toml::de::Error> = toml::from_str(&contents);
match config {
Ok(config) => Ok(config),
Err(e) => panic!("fail to parse config file: {}", e),
}
}
}
impl Connection {
pub fn database_url(&self) -> String {
match &self.database {
Some(database) => format!(
"mysql://{user}:@{host}:{port}/{database}",
user = self.user,
host = self.host,
port = self.port,
database = database
),
None => format!(
"mysql://{user}:@{host}:{port}",
user = self.user,
host = self.host,
port = self.port,
),
}
}
}
Loading…
Cancel
Save