summaryrefslogtreecommitdiff
path: root/src/cmds
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-03-18 22:50:03 +0800
committer魏曹先生 <1992414357@qq.com>2026-03-18 22:50:03 +0800
commit74bc8902be593796eb6292151e08374072766e3e (patch)
treef3de024bf06753649ff2a51587ee5e54a1c92435 /src/cmds
parent5372793a49567dcba7315bf8e7bc5a1cab2d5a76 (diff)
Add workspace sheet command with help and localization
Diffstat (limited to 'src/cmds')
-rw-r--r--src/cmds/arg/workspace_sheet.rs22
-rw-r--r--src/cmds/cmd/workspace_sheet.rs109
-rw-r--r--src/cmds/collect/workspace.rs5
-rw-r--r--src/cmds/comp/workspace_sheet.rs20
-rw-r--r--src/cmds/converter/make_sheet_error.rs22
-rw-r--r--src/cmds/converter/workspace_operation_error.rs59
-rw-r--r--src/cmds/in/workspace_sheet.rs6
7 files changed, 224 insertions, 19 deletions
diff --git a/src/cmds/arg/workspace_sheet.rs b/src/cmds/arg/workspace_sheet.rs
new file mode 100644
index 0000000..7cf65e4
--- /dev/null
+++ b/src/cmds/arg/workspace_sheet.rs
@@ -0,0 +1,22 @@
+// Why not directly design new, delete, print_path as Option<String>?
+// Because the former would only allow the following syntax:
+// jvn workspace sheet --new sheet
+// But by separating name and operation, it can simultaneously support:
+// jvn workspace sheet sheet --new
+
+#[derive(clap::Parser)]
+pub struct JVWorkspaceSheetArgument {
+ pub name: Option<String>,
+
+ #[arg(short = 'n', long = "new")]
+ pub new: bool,
+
+ #[arg(short = 'd', long = "delete")]
+ pub delete: bool,
+
+ #[arg(short = 'A', long = "list-all")]
+ pub list_all: bool,
+
+ #[arg(short = 'p', long = "print-path")]
+ pub print_path: bool,
+}
diff --git a/src/cmds/cmd/workspace_sheet.rs b/src/cmds/cmd/workspace_sheet.rs
new file mode 100644
index 0000000..a360203
--- /dev/null
+++ b/src/cmds/cmd/workspace_sheet.rs
@@ -0,0 +1,109 @@
+use crate::{
+ cmd_output,
+ cmds::{
+ arg::workspace_sheet::JVWorkspaceSheetArgument, collect::workspace::JVWorkspaceCollect,
+ converter::make_sheet_error::MakeSheetErrorConverter,
+ r#in::workspace_sheet::JVWorkspaceSheetInput, out::none::JVNoneOutput,
+ },
+ systems::{
+ cmd::{
+ cmd_system::{AnyOutput, JVCommandContext},
+ errors::{CmdExecuteError, CmdPrepareError},
+ },
+ helpdoc::helpdoc_viewer,
+ },
+};
+use cmd_system_macros::exec;
+use just_enough_vcs::system::workspace::workspace::manager::WorkspaceManager;
+use rust_i18n::t;
+
+pub struct JVWorkspaceSheetCommand;
+type Cmd = JVWorkspaceSheetCommand;
+type Arg = JVWorkspaceSheetArgument;
+type In = JVWorkspaceSheetInput;
+type Collect = JVWorkspaceCollect;
+
+async fn help_str() -> String {
+ helpdoc_viewer::display("commands/workspace/sheet").await;
+ String::new()
+}
+
+async fn prepare(_args: &Arg, _ctx: &JVCommandContext) -> Result<In, CmdPrepareError> {
+ let input = match (_args.new, _args.delete, _args.list_all, _args.print_path) {
+ (true, false, false, false) => {
+ let name = _args.name.as_ref().ok_or_else(|| {
+ CmdPrepareError::Error(
+ t!("workspace_sheet.error.sheet_name_required_for_new")
+ .trim()
+ .to_string(),
+ )
+ })?;
+ JVWorkspaceSheetInput::Add(name.clone())
+ }
+ (false, true, false, false) => {
+ let name = _args.name.as_ref().ok_or_else(|| {
+ CmdPrepareError::Error(
+ t!("workspace_sheet.error.sheet_name_required_for_delete")
+ .trim()
+ .to_string(),
+ )
+ })?;
+ JVWorkspaceSheetInput::Delete(name.clone())
+ }
+ (false, false, true, false) => JVWorkspaceSheetInput::ListAll,
+ (false, false, false, true) => {
+ let name = _args.name.as_ref().ok_or_else(|| {
+ CmdPrepareError::Error(
+ t!("workspace_sheet.error.sheet_name_required_for_print_path")
+ .trim()
+ .to_string(),
+ )
+ })?;
+ JVWorkspaceSheetInput::PrintPath(name.clone())
+ }
+ _ => {
+ return Err(CmdPrepareError::Error(
+ t!("workspace_sheet.error.exactly_one_required")
+ .trim()
+ .to_string(),
+ ));
+ }
+ };
+ Ok(input)
+}
+
+async fn collect(_args: &Arg, _ctx: &JVCommandContext) -> Result<Collect, CmdPrepareError> {
+ Ok(JVWorkspaceCollect {
+ manager: WorkspaceManager::new(),
+ })
+}
+
+#[exec]
+async fn exec(input: In, collect: Collect) -> Result<AnyOutput, CmdExecuteError> {
+ match input {
+ JVWorkspaceSheetInput::Add(sheet_name) => {
+ if let Err(e) = collect.manager.make_sheet(sheet_name).await {
+ return Err(MakeSheetErrorConverter::to_exec_error(e));
+ }
+ }
+ JVWorkspaceSheetInput::Delete(sheet_name) => {
+ if let Err(e) = collect.manager.drop_sheet(sheet_name).await {
+ return Err(MakeSheetErrorConverter::to_exec_error(e));
+ }
+ }
+ JVWorkspaceSheetInput::ListAll => {
+ collect
+ .manager
+ .list_sheet_names()
+ .await
+ .iter()
+ .for_each(|name| println!("{}", name));
+ }
+ JVWorkspaceSheetInput::PrintPath(sheet_name) => {
+ println!("{}", collect.manager.get_sheet_path(sheet_name).display())
+ }
+ }
+ cmd_output!(JVNoneOutput => JVNoneOutput)
+}
+
+crate::command_template!();
diff --git a/src/cmds/collect/workspace.rs b/src/cmds/collect/workspace.rs
new file mode 100644
index 0000000..5759a09
--- /dev/null
+++ b/src/cmds/collect/workspace.rs
@@ -0,0 +1,5 @@
+use just_enough_vcs::system::workspace::workspace::manager::WorkspaceManager;
+
+pub struct JVWorkspaceCollect {
+ pub manager: WorkspaceManager,
+}
diff --git a/src/cmds/comp/workspace_sheet.rs b/src/cmds/comp/workspace_sheet.rs
new file mode 100644
index 0000000..3d7e6d5
--- /dev/null
+++ b/src/cmds/comp/workspace_sheet.rs
@@ -0,0 +1,20 @@
+use crate::systems::comp::context::CompletionContext;
+use just_enough_vcs::system::workspace::workspace::manager::WorkspaceManager;
+
+pub fn comp(ctx: CompletionContext) -> Option<Vec<String>> {
+ if ctx.current_word.starts_with('-') {
+ return Some(vec![
+ "--list-all".to_string(),
+ "--print-path".to_string(),
+ "--new".to_string(),
+ "--delete".to_string(),
+ ]);
+ }
+
+ if ctx.previous_word == "--new" || ctx.previous_word == "-n" {
+ return Some(vec![]);
+ }
+
+ let rt = tokio::runtime::Runtime::new().unwrap();
+ Some(rt.block_on(WorkspaceManager::new().list_sheet_names()))
+}
diff --git a/src/cmds/converter/make_sheet_error.rs b/src/cmds/converter/make_sheet_error.rs
new file mode 100644
index 0000000..8bbc45d
--- /dev/null
+++ b/src/cmds/converter/make_sheet_error.rs
@@ -0,0 +1,22 @@
+use crate::systems::cmd::errors::CmdExecuteError;
+use just_enough_vcs::system::workspace::workspace::manager::sheet_state::error::MakeSheetError;
+use rust_i18n::t;
+
+pub struct MakeSheetErrorConverter;
+
+impl MakeSheetErrorConverter {
+ pub fn to_exec_error(err: MakeSheetError) -> CmdExecuteError {
+ match err {
+ MakeSheetError::SheetAlreadyExists => {
+ CmdExecuteError::Error(t!("make_sheet_error.sheet_already_exists").to_string())
+ }
+ MakeSheetError::SheetNotFound => {
+ CmdExecuteError::Error(t!("make_sheet_error.sheet_not_found").to_string())
+ }
+ MakeSheetError::Io(error) => CmdExecuteError::Io(error),
+ MakeSheetError::Other(error) => CmdExecuteError::Error(
+ t!("make_sheet_error.other", error = error.to_string()).to_string(),
+ ),
+ }
+ }
+}
diff --git a/src/cmds/converter/workspace_operation_error.rs b/src/cmds/converter/workspace_operation_error.rs
index f2f71d0..3e6252d 100644
--- a/src/cmds/converter/workspace_operation_error.rs
+++ b/src/cmds/converter/workspace_operation_error.rs
@@ -1,5 +1,6 @@
use crate::systems::cmd::errors::CmdExecuteError;
use just_enough_vcs::system::workspace::workspace::error::WorkspaceOperationError;
+use rust_i18n::t;
pub struct JVWorkspaceOperationErrorConverter;
@@ -9,26 +10,46 @@ impl JVWorkspaceOperationErrorConverter {
WorkspaceOperationError::Io(error) => CmdExecuteError::Io(error),
WorkspaceOperationError::Other(msg) => CmdExecuteError::Error(msg),
WorkspaceOperationError::ConfigNotFound => {
- CmdExecuteError::Error("Config not found".to_string())
- }
- WorkspaceOperationError::WorkspaceNotFound => {
- CmdExecuteError::Error("Workspace not found".to_string())
- }
- WorkspaceOperationError::HandleLock(handle_lock_error) => {
- CmdExecuteError::Error(format!("Handle lock error: {}", handle_lock_error))
- }
- WorkspaceOperationError::DataRead(data_read_error) => {
- CmdExecuteError::Error(format!("Data read error: {}", data_read_error))
- }
- WorkspaceOperationError::DataWrite(data_write_error) => {
- CmdExecuteError::Error(format!("Data write error: {}", data_write_error))
- }
- WorkspaceOperationError::DataApply(data_apply_error) => {
- CmdExecuteError::Error(format!("Data apply error: {}", data_apply_error))
- }
- WorkspaceOperationError::IDAliasError(id_alias_error) => {
- CmdExecuteError::Error(format!("ID alias error: {}", id_alias_error))
+ CmdExecuteError::Error(t!("workspace_operation_error.config_not_found").to_string())
}
+ WorkspaceOperationError::WorkspaceNotFound => CmdExecuteError::Error(
+ t!("workspace_operation_error.workspace_not_found").to_string(),
+ ),
+ WorkspaceOperationError::HandleLock(handle_lock_error) => CmdExecuteError::Error(
+ t!(
+ "workspace_operation_error.handle_lock",
+ error = handle_lock_error
+ )
+ .to_string(),
+ ),
+ WorkspaceOperationError::DataRead(data_read_error) => CmdExecuteError::Error(
+ t!(
+ "workspace_operation_error.data_read",
+ error = data_read_error
+ )
+ .to_string(),
+ ),
+ WorkspaceOperationError::DataWrite(data_write_error) => CmdExecuteError::Error(
+ t!(
+ "workspace_operation_error.data_write",
+ error = data_write_error
+ )
+ .to_string(),
+ ),
+ WorkspaceOperationError::DataApply(data_apply_error) => CmdExecuteError::Error(
+ t!(
+ "workspace_operation_error.data_apply",
+ error = data_apply_error
+ )
+ .to_string(),
+ ),
+ WorkspaceOperationError::IDAliasError(id_alias_error) => CmdExecuteError::Error(
+ t!(
+ "workspace_operation_error.id_alias_error",
+ error = id_alias_error
+ )
+ .to_string(),
+ ),
}
}
}
diff --git a/src/cmds/in/workspace_sheet.rs b/src/cmds/in/workspace_sheet.rs
new file mode 100644
index 0000000..78159ac
--- /dev/null
+++ b/src/cmds/in/workspace_sheet.rs
@@ -0,0 +1,6 @@
+pub enum JVWorkspaceSheetInput {
+ Add(String),
+ Delete(String),
+ ListAll,
+ PrintPath(String),
+}