pull/153/merge
kyoto7250 2 years ago committed by GitHub
commit 182a696073
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

12
Cargo.lock generated

@ -608,6 +608,7 @@ dependencies = [
"futures",
"itertools",
"pretty_assertions",
"ron",
"rust_decimal",
"serde",
"serde_json",
@ -1242,6 +1243,17 @@ dependencies = [
"winapi",
]
[[package]]
name = "ron"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b861ecaade43ac97886a512b360d01d66be9f41f3c61088b42cedf92e03d678"
dependencies = [
"base64",
"bitflags",
"serde",
]
[[package]]
name = "rsa"
version = "0.4.1"

@ -25,7 +25,8 @@ chrono = "0.4"
tokio = { version = "1.11.0", features = ["full"] }
futures = "0.3.5"
serde_json = "1.0"
serde = "1.0"
ron = "0.7"
serde = { version = "1", features = ["derive"] }
toml = "0.4"
strum = "0.21"
strum_macros = "0.21"

@ -106,6 +106,8 @@ If you want to add connections, you need to edit your config file. For more info
## Keymap
### Default keymap
| Key | Description |
| ---- | ---- |
| <kbd>h</kbd>, <kbd>j</kbd>, <kbd>k</kbd>, <kbd>l</kbd> | Scroll left/down/up/right |
@ -120,6 +122,16 @@ If you want to add connections, you need to edit your config file. For more info
| <kbd>1</kbd>, <kbd>2</kbd>, <kbd>3</kbd>, <kbd>4</kbd>, <kbd>5</kbd> | Switch to records/columns/constraints/foreign keys/indexes tab |
| <kbd>Esc</kbd> | Hide pop up |
### Custom keymap
The location of the file depends on your OS:
- macOS: `$HOME/.config/gobang/key_bind.ron`
- Linux: `$HOME/.config/gobang/key_bind.ron`
- Windows: `%APPDATA%/gobang/key_bind.ron`
A sample `key_bind.ron` is [here](https://github.com/TaKO8Ki/gobang/tree/main/examples/key_bind.ron).
## Configuration
The location of the file depends on your OS:
@ -128,34 +140,7 @@ The location of the file depends on your OS:
- Linux: `$HOME/.config/gobang/config.toml`
- Windows: `%APPDATA%/gobang/config.toml`
The following is a sample config.toml file:
```toml
[[conn]]
type = "mysql"
user = "root"
host = "localhost"
port = 3306
[[conn]]
type = "mysql"
user = "root"
host = "localhost"
port = 3306
password = "password"
database = "foo"
[[conn]]
type = "postgres"
user = "root"
host = "localhost"
port = 5432
database = "bar"
[[conn]]
type = "sqlite"
path = "/path/to/baz.db"
```
A sample `config.toml` file is [here](https://github.com/TaKO8Ki/gobang/tree/main/examples/config.toml)
## Contribution

@ -0,0 +1,24 @@
[[conn]]
type = "mysql"
user = "root"
host = "localhost"
port = 3306
[[conn]]
type = "mysql"
user = "root"
host = "localhost"
port = 3306
password = "password"
database = "foo"
[[conn]]
type = "postgres"
user = "root"
host = "localhost"
port = 5432
database = "bar"
[[conn]]
type = "sqlite"
path = "/path/to/baz.db"

@ -0,0 +1,46 @@
/*
* This file is a custom key configuration file.
* Place this file in `$HOME/.config/gobang/key_bind.ron`.
*
* You can find the available keys here
* https://github.com/TaKO8Ki/gobang/blob/b13e4bb255ea533db16240e1cb5138fca4241264/src/event/key.rs
*
* You can get the latest custom key configuration file here
* https://github.com/TaKO8Ki/gobang/blob/b13e4bb255ea533db16240e1cb5138fca4241264/examples/key_bind.ron
*/
(
scroll_up: Some(Char('k')),
scroll_down: Some(Char('j')),
scroll_right: Some(Char('l')),
scroll_left: Some(Char('h')),
move_up: Some(Up),
move_down: Some(Down),
copy: Some(Char('y')),
enter: Some(Enter),
exit: Some(Ctrl('c')),
quit: Some(Char('q')),
exit_popup: Some(Esc),
focus_right: Some(Right),
focus_left: Some(Left),
focus_above: Some(Up),
focus_connections: Some(Char('c')),
open_help: Some(Char('?')),
filter: Some(Char('/')),
scroll_down_multiple_lines: Some(Ctrl('d')),
scroll_up_multiple_lines: Some(Ctrl('u')),
scroll_to_top: Some(Char('g')),
scroll_to_bottom: Some(Char('G')),
extend_selection_by_one_cell_left: Some(Char('H')),
extend_selection_by_one_cell_right: Some(Char('L')),
extend_selection_by_one_cell_down: Some(Char('J')),
extend_selection_by_one_cell_up: Some(Char('K')),
tab_records: Some(Char('1')),
tab_properties: Some(Char('2')),
tab_sql_editor: Some(Char('3')),
tab_columns: Some(Char('4')),
tab_constraints: Some(Char('5')),
tab_foreign_keys: Some(Char('6')),
tab_indexes: Some(Char('7')),
extend_or_shorten_widget_width_to_right: Some(Char('>')),
extend_or_shorten_widget_width_to_left: Some(Char('<')),
)

@ -1,3 +1,4 @@
use crate::key_bind::KeyBind;
use crate::log::LogLevel;
use crate::Key;
use serde::Deserialize;
@ -15,6 +16,10 @@ pub struct CliConfig {
/// Set the config file
#[structopt(long, short, global = true)]
config_path: Option<std::path::PathBuf>,
/// Set the key bind file
#[structopt(long, short, global = true)]
key_bind_path: Option<std::path::PathBuf>,
}
#[derive(Debug, Deserialize, Clone)]
@ -26,6 +31,13 @@ pub struct Config {
pub log_level: LogLevel,
}
#[derive(Debug, Deserialize, Clone)]
pub struct ReadConfig {
pub conn: Vec<Connection>,
#[serde(default)]
pub log_level: LogLevel,
}
#[derive(Debug, Deserialize, Clone)]
enum DatabaseType {
#[serde(rename = "mysql")]
@ -78,7 +90,7 @@ pub struct Connection {
}
#[derive(Debug, Deserialize, Clone)]
#[cfg_attr(test, derive(Serialize))]
#[cfg_attr(test, derive(Serialize, PartialEq))]
pub struct KeyConfig {
pub scroll_up: Key,
pub scroll_down: Key,
@ -164,19 +176,35 @@ impl Config {
} else {
get_app_config_path()?.join("config.toml")
};
let key_bind_path = if let Some(key_bind_path) = &config.key_bind_path {
key_bind_path.clone()
} else {
get_app_config_path()?.join("key_bind.ron")
};
if let Ok(file) = File::open(config_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);
let config: Result<ReadConfig, toml::de::Error> = toml::from_str(&contents);
match config {
Ok(config) => return Ok(config),
Ok(config) => return Ok(Config::build(config, key_bind_path)),
Err(e) => panic!("fail to parse config file: {}", e),
}
}
Ok(Config::default())
}
fn build(read_config: ReadConfig, key_bind_path: PathBuf) -> Self {
let key_bind = KeyBind::load(key_bind_path).unwrap();
Config {
conn: read_config.conn,
log_level: read_config.log_level,
key_config: KeyConfig::from(key_bind),
}
}
}
impl Connection {
@ -325,10 +353,20 @@ fn expand_path(path: &Path) -> Option<PathBuf> {
#[cfg(test)]
mod test {
use super::{expand_path, KeyConfig, Path, PathBuf};
use super::{expand_path, CliConfig, Config, KeyConfig, Path, PathBuf};
use serde_json::Value;
use std::env;
#[test]
fn test_load_config() {
let cli_config = CliConfig {
config_path: Some(Path::new("examples/config.toml").to_path_buf()),
key_bind_path: Some(Path::new("examples/key_bind.ron").to_path_buf()),
};
assert_eq!(Config::new(&cli_config).is_ok(), true);
}
#[test]
fn test_overlappted_key() {
let value: Value =

@ -0,0 +1,164 @@
use crate::config::KeyConfig;
use crate::event::Key;
use serde::Deserialize;
use std::fs::File;
use std::io::{BufReader, Read};
use std::path::PathBuf;
#[derive(Debug, Deserialize, Clone, Default)]
pub struct KeyBind {
pub scroll_up: Option<Key>,
pub scroll_down: Option<Key>,
pub scroll_right: Option<Key>,
pub scroll_left: Option<Key>,
pub move_up: Option<Key>,
pub move_down: Option<Key>,
pub copy: Option<Key>,
pub enter: Option<Key>,
pub exit: Option<Key>,
pub quit: Option<Key>,
pub exit_popup: Option<Key>,
pub focus_right: Option<Key>,
pub focus_left: Option<Key>,
pub focus_above: Option<Key>,
pub focus_connections: Option<Key>,
pub open_help: Option<Key>,
pub filter: Option<Key>,
pub scroll_down_multiple_lines: Option<Key>,
pub scroll_up_multiple_lines: Option<Key>,
pub scroll_to_top: Option<Key>,
pub scroll_to_bottom: Option<Key>,
pub extend_selection_by_one_cell_left: Option<Key>,
pub extend_selection_by_one_cell_right: Option<Key>,
pub extend_selection_by_one_cell_up: Option<Key>,
pub extend_selection_by_one_cell_down: Option<Key>,
pub tab_records: Option<Key>,
pub tab_columns: Option<Key>,
pub tab_constraints: Option<Key>,
pub tab_foreign_keys: Option<Key>,
pub tab_indexes: Option<Key>,
pub tab_sql_editor: Option<Key>,
pub tab_properties: Option<Key>,
pub extend_or_shorten_widget_width_to_right: Option<Key>,
pub extend_or_shorten_widget_width_to_left: Option<Key>,
}
impl KeyBind {
pub fn load(config_path: PathBuf) -> anyhow::Result<Self> {
if let Ok(file) = File::open(config_path) {
let mut buf_reader = BufReader::new(file);
let mut contents = String::new();
buf_reader.read_to_string(&mut contents)?;
let key_bind: Result<KeyBind, ron::Error> = ron::from_str(&contents);
match key_bind {
Ok(key_bind) => return Ok(key_bind),
Err(e) => panic!("fail to parse key bind file: {}", e),
}
}
return Ok(Self::default());
}
}
macro_rules! merge {
($kc:expr, $kt:expr) => {
$kc = $kt.unwrap_or_else(|| $kc)
};
}
impl From<KeyBind> for KeyConfig {
#[allow(clippy::field_reassign_with_default)]
fn from(kb: KeyBind) -> Self {
let mut kc = KeyConfig::default();
merge!(kc.scroll_up, kb.scroll_up);
merge!(kc.scroll_down, kb.scroll_down);
merge!(kc.scroll_right, kb.scroll_right);
merge!(kc.scroll_left, kb.scroll_left);
merge!(kc.scroll_down, kb.scroll_down);
merge!(kc.move_up, kb.move_up);
merge!(kc.move_down, kb.move_down);
merge!(kc.copy, kb.copy);
merge!(kc.enter, kb.enter);
merge!(kc.exit, kb.exit);
merge!(kc.quit, kb.quit);
merge!(kc.exit_popup, kb.exit_popup);
merge!(kc.focus_right, kb.focus_right);
merge!(kc.focus_left, kb.focus_left);
merge!(kc.focus_above, kb.focus_above);
merge!(kc.focus_connections, kb.focus_connections);
merge!(kc.open_help, kb.open_help);
merge!(kc.filter, kb.filter);
merge!(kc.scroll_down_multiple_lines, kb.scroll_down_multiple_lines);
merge!(kc.scroll_up_multiple_lines, kb.scroll_up_multiple_lines);
merge!(kc.scroll_to_top, kb.scroll_to_top);
merge!(kc.scroll_to_bottom, kb.scroll_to_bottom);
merge!(
kc.extend_selection_by_one_cell_left,
kb.extend_selection_by_one_cell_left
);
merge!(
kc.extend_selection_by_one_cell_right,
kb.extend_selection_by_one_cell_right
);
merge!(
kc.extend_selection_by_one_cell_down,
kb.extend_selection_by_one_cell_down
);
merge!(
kc.extend_selection_by_one_cell_up,
kb.extend_selection_by_one_cell_up
);
merge!(kc.tab_records, kb.tab_records);
merge!(kc.tab_properties, kb.tab_properties);
merge!(kc.tab_sql_editor, kb.tab_sql_editor);
merge!(kc.tab_columns, kb.tab_columns);
merge!(kc.tab_constraints, kb.tab_constraints);
merge!(kc.tab_foreign_keys, kb.tab_foreign_keys);
merge!(kc.tab_indexes, kb.tab_indexes);
merge!(
kc.extend_or_shorten_widget_width_to_right,
kb.extend_or_shorten_widget_width_to_right
);
merge!(
kc.extend_or_shorten_widget_width_to_left,
kb.extend_or_shorten_widget_width_to_left
);
kc
}
}
#[cfg(test)]
mod test {
use super::KeyBind;
use crate::config::KeyConfig;
use crate::event::Key;
use std::path::Path;
#[test]
fn test_exist_file() {
let config_path = Path::new("examples/key_bind.ron").to_path_buf();
assert_eq!(config_path.exists(), true);
assert_eq!(KeyBind::load(config_path).is_ok(), true);
}
#[test]
fn test_not_exist_file() {
let config_path = Path::new("examples/not_exist.ron").to_path_buf();
assert_eq!(config_path.exists(), false);
assert_eq!(KeyBind::load(config_path).is_ok(), true);
}
#[test]
fn test_key_config_from_key_bind() {
// Default Config
let empty_kb = KeyBind::default();
let kc = KeyConfig::default();
assert_eq!(KeyConfig::from(empty_kb), kc);
// Merged Config
let mut kb = KeyBind::default();
kb.scroll_up = Some(Key::Char('M'));
let build_kc = KeyConfig::from(kb);
assert_eq!(build_kc.scroll_up, Key::Char('M'));
}
}

@ -5,6 +5,7 @@ mod components;
mod config;
mod database;
mod event;
mod key_bind;
mod ui;
mod version;

Loading…
Cancel
Save