refactor commands for better separation (#313)

* refactor commands for better separation

* fmt
This commit is contained in:
Conrad Ludgate 2022-04-21 10:12:56 +01:00 committed by GitHub
parent 24e2971787
commit d57f549855
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 226 additions and 204 deletions

133
src/command/client.rs Normal file
View file

@ -0,0 +1,133 @@
use clap::CommandFactory;
use clap::Subcommand;
use clap_complete::Shell;
use clap_complete::{generate, generate_to};
use eyre::{Result, WrapErr};
use atuin_client::database::Sqlite;
use atuin_client::settings::Settings;
use atuin_common::utils::uuid_v4;
mod event;
mod history;
mod import;
mod init;
mod login;
mod logout;
mod register;
mod search;
mod stats;
mod sync;
use std::path::PathBuf;
#[derive(Subcommand)]
#[clap(infer_subcommands = true)]
pub enum Cmd {
/// Manipulate shell history
#[clap(subcommand)]
History(history::Cmd),
/// Import shell history from file
#[clap(subcommand)]
Import(import::Cmd),
/// Calculate statistics for your history
#[clap(subcommand)]
Stats(stats::Cmd),
/// Output shell setup
#[clap(subcommand)]
Init(init::Cmd),
/// Generate a UUID
Uuid,
/// Interactive history search
Search(search::Cmd),
/// Sync with the configured server
Sync {
/// Force re-download everything
#[clap(long, short)]
force: bool,
},
/// Login to the configured server
Login(login::Cmd),
/// Log out
Logout,
/// Register with the configured server
Register(register::Cmd),
/// Print the encryption key for transfer to another machine
Key,
/// Generate shell completions
GenCompletions {
/// Set the shell for generating completions
#[clap(long, short)]
shell: Shell,
/// Set the output directory
#[clap(long, short)]
out_dir: Option<String>,
},
}
impl Cmd {
pub async fn run(self) -> Result<()> {
pretty_env_logger::init();
let settings = Settings::new().wrap_err("could not load client settings")?;
let db_path = PathBuf::from(settings.db_path.as_str());
let mut db = Sqlite::new(db_path).await?;
match self {
Self::History(history) => history.run(&settings, &mut db).await,
Self::Import(import) => import.run(&mut db).await,
Self::Stats(stats) => stats.run(&mut db, &settings).await,
Self::Init(init) => {
init.run();
Ok(())
}
Self::Search(search) => search.run(&mut db, &settings).await,
Self::Sync { force } => sync::run(&settings, force, &mut db).await,
Self::Login(l) => l.run(&settings).await,
Self::Logout => logout::run(),
Self::Register(r) => r.run(&settings).await,
Self::Key => {
use atuin_client::encryption::{encode_key, load_key};
let key = load_key(&settings).wrap_err("could not load encryption key")?;
let encode = encode_key(key).wrap_err("could not encode encryption key")?;
println!("{}", encode);
Ok(())
}
Self::Uuid => {
println!("{}", uuid_v4());
Ok(())
}
Self::GenCompletions { shell, out_dir } => {
let mut cli = crate::Atuin::command();
match out_dir {
Some(out_dir) => {
generate_to(shell, &mut cli, env!("CARGO_PKG_NAME"), &out_dir)?;
}
None => {
generate(
shell,
&mut cli,
env!("CARGO_PKG_NAME"),
&mut std::io::stdout(),
);
}
}
Ok(())
}
}
}
}

View file

@ -11,17 +11,17 @@ pub enum Cmd {
}
fn init_zsh() {
let full = include_str!("../shell/atuin.zsh");
let full = include_str!("../../shell/atuin.zsh");
println!("{}", full);
}
fn init_bash() {
let full = include_str!("../shell/atuin.bash");
let full = include_str!("../../shell/atuin.bash");
println!("{}", full);
}
fn init_fish() {
let full = include_str!("../shell/atuin.fish");
let full = include_str!("../../shell/atuin.fish");
println!("{}", full);
}

View file

@ -1,12 +1,15 @@
use eyre::{Context, Result};
use fs_err::remove_file;
pub fn run() {
pub fn run() -> Result<()> {
let session_path = atuin_common::utils::data_dir().join("session");
if session_path.exists() {
remove_file(session_path.as_path()).expect("Failed to remove session file");
remove_file(session_path.as_path()).context("Failed to remove session file")?;
println!("You have logged out!");
} else {
println!("You are not logged in");
}
Ok(())
}

View file

@ -19,6 +19,12 @@ pub struct Cmd {
pub password: Option<String>,
}
impl Cmd {
pub async fn run(self, settings: &Settings) -> Result<()> {
run(settings, &self.username, &self.email, &self.password).await
}
}
pub async fn run(
settings: &Settings,
username: &Option<String>,

View file

@ -1,7 +1,7 @@
use chrono::Utc;
use clap::Parser;
use eyre::Result;
use std::{io::stdout, ops::Sub, time::Duration};
use termion::{event::Key, input::MouseTerminal, raw::IntoRawMode, screen::AlternateScreen};
use tui::{
backend::{Backend, TermionBackend},
@ -19,10 +19,75 @@ use atuin_client::{
settings::{SearchMode, Settings},
};
use crate::command::event::{Event, Events};
use super::event::{Event, Events};
const VERSION: &str = env!("CARGO_PKG_VERSION");
#[derive(Parser)]
pub struct Cmd {
/// Filter search result by directory
#[clap(long, short)]
cwd: Option<String>,
/// Exclude directory from results
#[clap(long = "exclude-cwd")]
exclude_cwd: Option<String>,
/// Filter search result by exit code
#[clap(long, short)]
exit: Option<i64>,
/// Exclude results with this exit code
#[clap(long = "exclude-exit")]
exclude_exit: Option<i64>,
/// Only include results added before this date
#[clap(long, short)]
before: Option<String>,
/// Only include results after this date
#[clap(long)]
after: Option<String>,
/// Open interactive search UI
#[clap(long, short)]
interactive: bool,
/// Use human-readable formatting for time
#[clap(long)]
human: bool,
query: Vec<String>,
/// Show only the text of the command
#[clap(long)]
cmd_only: bool,
}
impl Cmd {
pub async fn run(
self,
db: &mut (impl Database + Send + Sync),
settings: &Settings,
) -> Result<()> {
run(
settings,
self.cwd,
self.exit,
self.interactive,
self.human,
self.exclude_exit,
self.exclude_cwd,
self.before,
self.after,
self.cmd_only,
&self.query,
db,
)
.await
}
}
struct State {
input: String,

View file

@ -1,212 +1,25 @@
use std::path::PathBuf;
use clap::CommandFactory;
use clap::Subcommand;
use clap_complete::Shell;
use clap_complete::{generate, generate_to};
use eyre::{Result, WrapErr};
use eyre::Result;
use atuin_client::database::Sqlite;
use atuin_client::settings::Settings as ClientSettings;
use atuin_common::utils::uuid_v4;
use atuin_server::settings::Settings as ServerSettings;
mod event;
mod history;
mod import;
mod init;
mod login;
mod logout;
mod register;
mod search;
mod client;
mod server;
mod stats;
mod sync;
#[derive(Subcommand)]
#[clap(infer_subcommands = true)]
pub enum AtuinCmd {
/// Manipulate shell history
#[clap(subcommand)]
History(history::Cmd),
/// Import shell history from file
#[clap(subcommand)]
Import(import::Cmd),
#[clap(flatten)]
Client(client::Cmd),
/// Start an atuin server
#[clap(subcommand)]
Server(server::Cmd),
/// Calculate statistics for your history
#[clap(subcommand)]
Stats(stats::Cmd),
/// Output shell setup
#[clap(subcommand)]
Init(init::Cmd),
/// Generate a UUID
Uuid,
/// Interactive history search
Search {
/// Filter search result by directory
#[clap(long, short)]
cwd: Option<String>,
/// Exclude directory from results
#[clap(long = "exclude-cwd")]
exclude_cwd: Option<String>,
/// Filter search result by exit code
#[clap(long, short)]
exit: Option<i64>,
/// Exclude results with this exit code
#[clap(long = "exclude-exit")]
exclude_exit: Option<i64>,
/// Only include results added before this date
#[clap(long, short)]
before: Option<String>,
/// Only include results after this date
#[clap(long)]
after: Option<String>,
/// Open interactive search UI
#[clap(long, short)]
interactive: bool,
/// Use human-readable formatting for time
#[clap(long)]
human: bool,
query: Vec<String>,
/// Show only the text of the command
#[clap(long)]
cmd_only: bool,
},
/// Sync with the configured server
Sync {
/// Force re-download everything
#[clap(long, short)]
force: bool,
},
/// Login to the configured server
Login(login::Cmd),
/// Log out
Logout,
/// Register with the configured server
Register(register::Cmd),
/// Print the encryption key for transfer to another machine
Key,
/// Generate shell completions
GenCompletions {
/// Set the shell for generating completions
#[clap(long, short)]
shell: Shell,
/// Set the output directory
#[clap(long, short)]
out_dir: Option<String>,
},
}
impl AtuinCmd {
pub async fn run(self) -> Result<()> {
let client_settings = ClientSettings::new().wrap_err("could not load client settings")?;
let server_settings = ServerSettings::new().wrap_err("could not load server settings")?;
let db_path = PathBuf::from(client_settings.db_path.as_str());
let mut db = Sqlite::new(db_path).await?;
match self {
Self::History(history) => history.run(&client_settings, &mut db).await,
Self::Import(import) => import.run(&mut db).await,
Self::Server(server) => server.run(server_settings).await,
Self::Stats(stats) => stats.run(&mut db, &client_settings).await,
Self::Init(init) => {
init.run();
Ok(())
}
Self::Search {
cwd,
exit,
interactive,
human,
exclude_exit,
exclude_cwd,
before,
after,
query,
cmd_only,
} => {
search::run(
&client_settings,
cwd,
exit,
interactive,
human,
exclude_exit,
exclude_cwd,
before,
after,
cmd_only,
&query,
&mut db,
)
.await
}
Self::Sync { force } => sync::run(&client_settings, force, &mut db).await,
Self::Login(l) => l.run(&client_settings).await,
Self::Logout => {
logout::run();
Ok(())
}
Self::Register(r) => {
register::run(&client_settings, &r.username, &r.email, &r.password).await
}
Self::Key => {
use atuin_client::encryption::{encode_key, load_key};
let key = load_key(&client_settings).wrap_err("could not load encryption key")?;
let encode = encode_key(key).wrap_err("could not encode encryption key")?;
println!("{}", encode);
Ok(())
}
Self::Uuid => {
println!("{}", uuid_v4());
Ok(())
}
Self::GenCompletions { shell, out_dir } => {
let mut cli = crate::Atuin::command();
match out_dir {
Some(out_dir) => {
generate_to(shell, &mut cli, env!("CARGO_PKG_NAME"), &out_dir)?;
}
None => {
generate(
shell,
&mut cli,
env!("CARGO_PKG_NAME"),
&mut std::io::stdout(),
);
}
}
Ok(())
}
Self::Client(client) => client.run().await,
Self::Server(server) => server.run().await,
}
}
}

View file

@ -1,5 +1,5 @@
use clap::Parser;
use eyre::Result;
use eyre::{Context, Result};
use atuin_server::launch;
use atuin_server::settings::Settings;
@ -20,7 +20,11 @@ pub enum Cmd {
}
impl Cmd {
pub async fn run(&self, settings: Settings) -> Result<()> {
pub async fn run(self) -> Result<()> {
pretty_env_logger::init();
let settings = Settings::new().wrap_err("could not load server settings")?;
match self {
Self::Start { host, port } => {
let host = host

View file

@ -33,7 +33,5 @@ impl Atuin {
#[tokio::main]
async fn main() -> Result<()> {
pretty_env_logger::init();
Atuin::parse().run().await
}