summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/cmd_system.rs29
-rw-r--r--src/cmd/cmds/status.rs105
-rw-r--r--src/cmd/cmds/template.rs2
-rw-r--r--src/cmd/errors.rs32
-rw-r--r--src/cmd/processer.rs3
-rw-r--r--src/cmd/renderers.rs1
-rw-r--r--src/cmd/renderers/json_renderer.rs44
7 files changed, 195 insertions, 21 deletions
diff --git a/src/cmd/cmd_system.rs b/src/cmd/cmd_system.rs
index 3edd5cc..229c7f0 100644
--- a/src/cmd/cmd_system.rs
+++ b/src/cmd/cmd_system.rs
@@ -2,7 +2,7 @@ use serde::Serialize;
use crate::{
cmd::{
- errors::{CmdExecuteError, CmdPrepareError, CmdProcessError},
+ errors::{CmdExecuteError, CmdPrepareError, CmdProcessError, CmdRenderError},
renderer::{JVRenderResult, JVResultRenderer},
},
r_println,
@@ -24,11 +24,30 @@ where
/// Get help string for the command
fn get_help_str() -> String;
+ /// Process the command with a specified renderer, performing any necessary post-execution processing
+ #[rustfmt::skip]
+ fn process_with_renderer_flag(
+ args: Vec<String>,
+ ctx: JVCommandContext,
+ renderer: String,
+ ) -> impl Future<Output = Result<JVRenderResult, CmdProcessError>> + Send
+ where
+ Self: Sync,
+ {
+ async move {
+ let renderer_str = renderer.as_str();
+ include!(concat!(
+ env!("CARGO_MANIFEST_DIR"),
+ "/src/cmd/renderers/renderer_list.txt"
+ ))
+ }
+ }
+
/// performing any necessary post-execution processing
fn process(
args: Vec<String>,
ctx: JVCommandContext,
- ) -> impl Future<Output = Result<JVRenderResult, CmdProcessError>> + Send + Sync
+ ) -> impl Future<Output = Result<JVRenderResult, CmdProcessError>> + Send
where
Self: Sync,
{
@@ -40,7 +59,7 @@ where
fn process_with_renderer<R: JVResultRenderer<Output> + Send + Sync>(
args: Vec<String>,
ctx: JVCommandContext,
- ) -> impl Future<Output = Result<JVRenderResult, CmdProcessError>> + Send + Sync
+ ) -> impl Future<Output = Result<JVRenderResult, CmdProcessError>> + Send
where
Self: Sync,
{
@@ -77,9 +96,9 @@ where
fn prepare(
args: Argument,
ctx: JVCommandContext,
- ) -> impl Future<Output = Result<Input, CmdPrepareError>> + Send + Sync;
+ ) -> impl Future<Output = Result<Input, CmdPrepareError>> + Send;
/// Run the command phase,
/// returning an output structure, waiting for rendering
- fn exec(args: Input) -> impl Future<Output = Result<Output, CmdExecuteError>> + Send + Sync;
+ fn exec(input: Input) -> impl Future<Output = Result<Output, CmdExecuteError>> + Send;
}
diff --git a/src/cmd/cmds/status.rs b/src/cmd/cmds/status.rs
index bbc78e8..d73a28a 100644
--- a/src/cmd/cmds/status.rs
+++ b/src/cmd/cmds/status.rs
@@ -1,10 +1,28 @@
+use std::{
+ collections::{HashMap, HashSet},
+ path::PathBuf,
+ time::SystemTime,
+};
+
use clap::Parser;
+use just_enough_vcs::vcs::data::{
+ local::workspace_analyzer::{
+ CreatedRelativePathBuf, FromRelativePathBuf, LostRelativePathBuf, ModifiedRelativePathBuf,
+ ToRelativePathBuf,
+ },
+ member::MemberId,
+ sheet::SheetName,
+ vault::virtual_file::VirtualFileId,
+};
use serde::Serialize;
-use crate::cmd::{
- cmd_system::{JVCommand, JVCommandContext},
- errors::{CmdExecuteError, CmdPrepareError, CmdRenderError},
- renderer::{JVRenderResult, JVResultRenderer},
+use crate::{
+ cmd::{
+ cmd_system::{JVCommand, JVCommandContext},
+ errors::{CmdExecuteError, CmdPrepareError, CmdRenderError},
+ renderer::{JVRenderResult, JVResultRenderer},
+ },
+ utils::workspace_reader::LocalWorkspaceReader,
};
pub struct JVStatusCommand;
@@ -12,23 +30,82 @@ pub struct JVStatusCommand;
#[derive(Parser, Debug)]
pub struct JVStatusArgument;
-pub struct JVStatusInput;
-
#[derive(Serialize)]
-pub struct JVStatusOutput;
+pub struct JVStatusResult {
+ pub current_account: MemberId,
+ pub current_sheet: SheetName,
+ pub moved: HashMap<VirtualFileId, (FromRelativePathBuf, ToRelativePathBuf)>,
+ pub created: HashSet<CreatedRelativePathBuf>,
+ pub lost: HashSet<LostRelativePathBuf>,
+ pub erased: HashSet<PathBuf>,
+ pub modified: HashSet<ModifiedRelativePathBuf>,
+ pub update_time: SystemTime,
+ pub now_time: SystemTime,
+}
+
+impl Default for JVStatusResult {
+ fn default() -> Self {
+ Self {
+ current_account: MemberId::default(),
+ current_sheet: SheetName::default(),
+ moved: HashMap::default(),
+ created: HashSet::default(),
+ lost: HashSet::default(),
+ erased: HashSet::default(),
+ modified: HashSet::default(),
+ update_time: SystemTime::now(),
+ now_time: SystemTime::now(),
+ }
+ }
+}
-impl JVCommand<JVStatusArgument, JVStatusInput, JVStatusOutput, JVStatusRenderer>
+impl JVCommand<JVStatusArgument, JVStatusResult, JVStatusResult, JVStatusRenderer>
for JVStatusCommand
{
async fn prepare(
_args: JVStatusArgument,
_ctx: JVCommandContext,
- ) -> Result<JVStatusInput, CmdPrepareError> {
- Ok(JVStatusInput)
+ ) -> Result<JVStatusResult, CmdPrepareError> {
+ // Initialize a reader for the local workspace and a default result structure
+ let mut reader = LocalWorkspaceReader::default();
+ let mut input = JVStatusResult::default();
+
+ // Analyze the current status of the local workspace
+ // (detects changes like created, modified, moved, etc.)
+ let analyzed = reader.analyze_local_status().await?;
+
+ // Retrieve the current account (member) ID
+ let account = reader.current_account().await?;
+
+ // Retrieve the name of the current sheet
+ let sheet_name = reader.sheet_name().await?;
+
+ // Get the timestamp of the last update, defaulting to the current time if not available
+ let update_time = reader
+ .latest_info()
+ .await?
+ .update_instant
+ .unwrap_or(SystemTime::now());
+
+ // Record the current system time
+ let now_time = SystemTime::now();
+
+ // Populate the result structure with the gathered data
+ input.current_account = account;
+ input.current_sheet = sheet_name;
+ input.moved = analyzed.moved;
+ input.created = analyzed.created;
+ input.lost = analyzed.lost;
+ input.erased = analyzed.erased;
+ input.modified = analyzed.modified;
+ input.update_time = update_time;
+ input.now_time = now_time;
+
+ Ok(input)
}
- async fn exec(args: JVStatusInput) -> Result<JVStatusOutput, CmdExecuteError> {
- todo!()
+ async fn exec(input: JVStatusResult) -> Result<JVStatusResult, CmdExecuteError> {
+ Ok(input) // Analyze command, no needs execute
}
fn get_help_str() -> String {
@@ -38,8 +115,8 @@ impl JVCommand<JVStatusArgument, JVStatusInput, JVStatusOutput, JVStatusRenderer
pub struct JVStatusRenderer;
-impl JVResultRenderer<JVStatusOutput> for JVStatusRenderer {
- async fn render(data: &JVStatusOutput) -> Result<JVRenderResult, CmdRenderError> {
+impl JVResultRenderer<JVStatusResult> for JVStatusRenderer {
+ async fn render(data: &JVStatusResult) -> Result<JVRenderResult, CmdRenderError> {
todo!()
}
}
diff --git a/src/cmd/cmds/template.rs b/src/cmd/cmds/template.rs
index 8874121..1c56c29 100644
--- a/src/cmd/cmds/template.rs
+++ b/src/cmd/cmds/template.rs
@@ -27,7 +27,7 @@ impl JVCommand<JVUnknownArgument, JVUnknownInput, JVUnknownOutput, JVStatusRende
todo!()
}
- async fn exec(_args: JVUnknownInput) -> Result<JVUnknownOutput, CmdExecuteError> {
+ async fn exec(_input: JVUnknownInput) -> Result<JVUnknownOutput, CmdExecuteError> {
todo!()
}
diff --git a/src/cmd/errors.rs b/src/cmd/errors.rs
index e1cf835..358d15a 100644
--- a/src/cmd/errors.rs
+++ b/src/cmd/errors.rs
@@ -1,3 +1,5 @@
+use just_enough_vcs::vcs::data::{member::MemberId, sheet::SheetName};
+
#[derive(thiserror::Error, Debug)]
pub enum CmdPrepareError {
#[error("IO error: {0}")]
@@ -5,6 +7,30 @@ pub enum CmdPrepareError {
#[error("{0}")]
Error(String),
+
+ #[error("LocalWorkspace not found")]
+ LocalWorkspaceNotFound,
+
+ #[error("LocalConfig not found")]
+ LocalConfigNotFound,
+
+ #[error("LatestInfo not found")]
+ LatestInfoNotFound,
+
+ #[error("LatestFileData of {0} not found")]
+ LatestFileDataNotExist(MemberId),
+
+ #[error("CachedSheet `{0}` not found")]
+ CachedSheetNotFound(SheetName),
+
+ #[error("LocalSheet `{0}/{1}` not found")]
+ LocalSheetNotFound(MemberId, SheetName),
+
+ #[error("LocalStatusAnalyzeFailed")]
+ LocalStatusAnalyzeFailed,
+
+ #[error("No sheet in use")]
+ NoSheetInUse,
}
impl CmdPrepareError {
@@ -44,6 +70,12 @@ pub enum CmdRenderError {
#[error("{0}")]
Error(String),
+
+ #[error("Serialize failed, {0}")]
+ SerializeFailed(String),
+
+ #[error("Renderer `{0}` not found")]
+ RendererNotFound(String),
}
impl CmdRenderError {
diff --git a/src/cmd/processer.rs b/src/cmd/processer.rs
index bc84b7d..f5fc2a6 100644
--- a/src/cmd/processer.rs
+++ b/src/cmd/processer.rs
@@ -6,6 +6,7 @@ use crate::cmd::renderer::JVRenderResult;
pub async fn jv_cmd_process(
args: Vec<String>,
ctx: JVCommandContext,
+ renderer_override: String,
) -> Result<JVRenderResult, CmdProcessError> {
let nodes = jv_cmd_nodes();
let command = args.join(" ");
@@ -25,7 +26,7 @@ pub async fn jv_cmd_process(
let matched_prefix = matching_nodes[0];
let prefix_len = matched_prefix.split_whitespace().count();
let trimmed_args: Vec<String> = args.into_iter().skip(prefix_len).collect();
- return jv_cmd_process_node(matched_prefix, trimmed_args, ctx).await;
+ return jv_cmd_process_node(matched_prefix, trimmed_args, ctx, renderer_override).await;
}
_ => {
// Multiple matching nodes found
diff --git a/src/cmd/renderers.rs b/src/cmd/renderers.rs
new file mode 100644
index 0000000..91fa88e
--- /dev/null
+++ b/src/cmd/renderers.rs
@@ -0,0 +1 @@
+pub mod json_renderer;
diff --git a/src/cmd/renderers/json_renderer.rs b/src/cmd/renderers/json_renderer.rs
new file mode 100644
index 0000000..14c1f81
--- /dev/null
+++ b/src/cmd/renderers/json_renderer.rs
@@ -0,0 +1,44 @@
+use serde::Serialize;
+use serde_json;
+
+use crate::{
+ cmd::{
+ errors::CmdRenderError,
+ renderer::{JVRenderResult, JVResultRenderer},
+ },
+ r_print,
+};
+
+pub struct JVResultJsonRenderer;
+
+impl<T> JVResultRenderer<T> for JVResultJsonRenderer
+where
+ T: Serialize + Sync,
+{
+ async fn render(data: &T) -> Result<JVRenderResult, CmdRenderError> {
+ let mut r = JVRenderResult::default();
+ let json_string = serde_json::to_string(data)
+ .map_err(|e| CmdRenderError::SerializeFailed(e.to_string()))?;
+
+ r_print!(r, "{}", json_string);
+
+ Ok(r)
+ }
+}
+
+pub struct JVResultPrettyJsonRenderer;
+
+impl<T> JVResultRenderer<T> for JVResultPrettyJsonRenderer
+where
+ T: Serialize + Sync,
+{
+ async fn render(data: &T) -> Result<JVRenderResult, CmdRenderError> {
+ let mut r = JVRenderResult::default();
+ let json_string = serde_json::to_string_pretty(data)
+ .map_err(|e| CmdRenderError::SerializeFailed(e.to_string()))?;
+
+ r_print!(r, "{}", json_string);
+
+ Ok(r)
+ }
+}