Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mypull requests #20

Merged
merged 3 commits into from
Jun 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
/target
zhobo
zhobo.yml
zhobo.log
# Generated by Cargo
# will have compiled files and executables
debug/
target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk

# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
.vscode/
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ clap = "4.5.7"
structopt = "0.3.26"
syntect = { version = "5.0", default-features = false, features = ["metadata", "default-fancy"]}
unicode-segmentation = "1.11.0"
ron = "0.8.1"

[target.'cfg(all(target_family="unix",not(target_os="macos")))'.dependencies]
which = "6.0.1"
Expand Down
54 changes: 18 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# dolce
# zhobo

`dolce` is the rebaked [gobang project](https://github.com/TaKO8Ki/gobang).
`zhobo` is the rebaked [gobang project](https://github.com/TaKO8Ki/gobang).

## Features
- Cross-platform support (macOS, Windows, Linux)
Expand All @@ -26,7 +26,10 @@
| <kbd>h</kbd>, <kbd>j</kbd>, <kbd>k</kbd>, <kbd>l</kbd> | Scroll left/down/up/right |
| <kbd>Ctrl</kbd> + <kbd>u</kbd>, <kbd>Ctrl</kbd> + <kbd>d</kbd> | Scroll up/down multiple lines |
| <kbd>g</kbd> , <kbd>G</kbd> | Scroll to top/bottom |
| <kbd>^</kbd>, <kbd>$</kbd> | Move to head/tail of line |
| <kbd>s</kbd> | Sort by selected column |
| <kbd>H</kbd>, <kbd>J</kbd>, <kbd>K</kbd>, <kbd>L</kbd> | Extend selection by one cell left/down/up/right |
| <kbd>V</kbd> | Extend selection by horizontal line |
| <kbd>y</kbd> | Copy a cell value |
| <kbd>←</kbd>, <kbd>→</kbd> | Move focus to left/right |
| <kbd>c</kbd> | Move focus to connections |
Expand All @@ -42,43 +45,22 @@

The location of the file depends on your OS:

- macOS: `$HOME/.config/gobang/config.toml`
- 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"
name = "mysql Foo DB"

[[conn]]
type = "postgres"
user = "root"
host = "localhost"
port = 5432
database = "bar"
name = "postgres Bar DB"

[[conn]]
type = "sqlite"
path = "/path/to/baz.db"
```
- macOS: `$HOME/.config/zhobo/config.toml`
- Linux: `$HOME/.config/zhobo/config.toml`
- Windows: `%APPDATA%/zhobo/config.toml`

Sample config.toml file is `examples/config.toml`:

### custom keymap

The location of the file depends on your OS:

- macOS: `$HOME/.config/zhobo/key_bind.ron`
- Linux: `$HOME/.config/zhobo/key_bind.ron`
- Windows: `%APPDATA%/zhobo/key_bind.ron`

Sample config.toml file is `examples/key_bind.ron`:

## contribution

Contributions are welcome.
Expand Down
26 changes: 26 additions & 0 deletions examples/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[[conn]]
type = "mysql"
user = "root"
host = "localhost"
port = 3306

[[conn]]
type = "mysql"
user = "root"
host = "localhost"
port = 3306
password = "password"
database = "foo"
name = "mysql Foo DB"

[[conn]]
type = "postgres"
user = "root"
host = "localhost"
port = 5432
database = "bar"
name = "postgres Bar DB"

[[conn]]
type = "sqlite"
path = "/path/to/baz.db"
44 changes: 44 additions & 0 deletions examples/key_bind.ron
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* This file is a custom key configuration file.
* Place this file in `$HOME/.config/zhobo/key_bind.ron`.
*/
(
scroll_up: Some(Char('k')),
scroll_down: Some(Char('j')),
scroll_right: Some(Char('l')),
scroll_left: Some(Char('h')),
sort_by_column: Some(Char('s')),
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')),
move_to_head_of_line: Some(Char('^')),
move_to_tail_of_line: Some(Char('$')),
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_horizontal_line: Some(Char('V')),
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('<')),
)
87 changes: 80 additions & 7 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::components::{
use crate::config::Config;
use crate::database::{MySqlPool, Pool, PostgresPool, SqlitePool, RECORDS_LIMIT_PER_PAGE};
use crate::event::Key;
use ratatui::layout::Flex;
use ratatui::{
layout::{Constraint, Direction, Layout, Rect},
Frame,
Expand Down Expand Up @@ -82,6 +83,7 @@ impl App {

let right_chunks = Layout::default()
.direction(Direction::Vertical)
.flex(Flex::Legacy)
.constraints([Constraint::Length(3), Constraint::Length(5)].as_ref())
.split(main_chunks[1]);

Expand Down Expand Up @@ -139,6 +141,7 @@ impl App {
if let Some(pool) = self.pool.as_ref() {
pool.close().await;
}

self.pool = if conn.is_mysql() {
Some(Box::new(
MySqlPool::new(conn.database_url()?.as_str()).await?,
Expand All @@ -162,7 +165,12 @@ impl App {
Ok(())
}

async fn update_record_table(&mut self) -> anyhow::Result<()> {
async fn update_record_table(
&mut self,
orders: Option<String>,
header_icons: Option<Vec<String>>,
hold_cursor_position: bool,
) -> anyhow::Result<()> {
if let Some((database, table)) = self.databases.tree().selected_table() {
let (headers, records) = self
.pool
Expand All @@ -177,10 +185,16 @@ impl App {
} else {
Some(self.record_table.filter.input_str())
},
orders,
)
.await?;
self.record_table
.update(records, headers, database.clone(), table.clone());
self.record_table.update(
records,
self.concat_headers(headers, header_icons),
database.clone(),
table.clone(),
hold_cursor_position,
);
}
Ok(())
}
Expand Down Expand Up @@ -230,10 +244,15 @@ impl App {
.pool
.as_ref()
.unwrap()
.get_records(&database, &table, 0, None)
.get_records(&database, &table, 0, None, None)
.await?;
self.record_table
.update(records, headers, database.clone(), table.clone());
self.record_table.update(
records,
headers,
database.clone(),
table.clone(),
false,
);
self.properties
.update(database.clone(), table.clone(), self.pool.as_ref().unwrap())
.await?;
Expand All @@ -249,6 +268,17 @@ impl App {
return Ok(EventState::Consumed);
};

if key == self.config.key_config.sort_by_column
&& !self.record_table.table.headers.is_empty()
{
self.record_table.table.add_order();
let order_query = self.record_table.table.generate_order_query();
let header_icons = self.record_table.table.generate_header_icons();
self.update_record_table(order_query, Some(header_icons), true)
.await?;
return Ok(EventState::Consumed);
};

if key == self.config.key_config.copy {
if let Some(text) = self.record_table.table.selected_cells() {
copy_to_clipboard(text.as_str())?
Expand All @@ -258,7 +288,10 @@ impl App {
if key == self.config.key_config.enter && self.record_table.filter_focused()
{
self.record_table.focus = crate::components::record_table::Focus::Table;
self.update_record_table().await?;
let order_query = self.record_table.table.generate_order_query();
let header_icons = self.record_table.table.generate_header_icons();
self.update_record_table(order_query, Some(header_icons), false)
.await?;
}

if self.record_table.table.eod {
Expand All @@ -283,6 +316,7 @@ impl App {
} else {
Some(self.record_table.filter.input_str())
},
None,
)
.await?;
if !records.is_empty() {
Expand Down Expand Up @@ -321,6 +355,24 @@ impl App {
Ok(EventState::NotConsumed)
}

fn concat_headers(
&self,
headers: Vec<String>,
header_icons: Option<Vec<String>>,
) -> Vec<String> {
if let Some(header_icons) = &header_icons {
let mut new_headers = vec![String::new(); headers.len()];
for (index, header) in headers.iter().enumerate() {
new_headers[index] = format!("{} {}", header, header_icons[index])
.trim()
.to_string();
}
return new_headers;
}

headers
}

fn extend_or_shorten_widget_width(&mut self, key: Key) -> anyhow::Result<EventState> {
if key
== self
Expand Down Expand Up @@ -408,4 +460,25 @@ mod test {
);
assert_eq!(app.left_main_chunk_percentage, 15);
}

#[test]
fn test_concat_headers() {
let app = App::new(Config::default());
let headers = vec![
"ID".to_string(),
"NAME".to_string(),
"TIMESTAMP".to_string(),
];
let header_icons = vec!["".to_string(), "↑1".to_string(), "↓2".to_string()];
let concat_headers: Vec<String> = app.concat_headers(headers, Some(header_icons));

assert_eq!(
concat_headers,
vec![
"ID".to_string(),
"NAME ↑1".to_string(),
"TIMESTAMP ↓2".to_string()
]
)
}
}
Loading
Loading