summaryrefslogtreecommitdiff
path: root/systems
diff options
context:
space:
mode:
Diffstat (limited to 'systems')
-rw-r--r--systems/_framework/src/space.rs6
-rw-r--r--systems/workspace/src/workspace/manager.rs2
-rw-r--r--systems/workspace/src/workspace/manager/sheet_state.rs67
-rw-r--r--systems/workspace/src/workspace/manager/sheet_state/error.rs29
4 files changed, 95 insertions, 9 deletions
diff --git a/systems/_framework/src/space.rs b/systems/_framework/src/space.rs
index 8a9b2ec..315bf2b 100644
--- a/systems/_framework/src/space.rs
+++ b/systems/_framework/src/space.rs
@@ -376,6 +376,12 @@ impl<T: SpaceRoot> Space<T> {
let path = self.local_path(relative_path)?;
Ok(tokio::fs::write(path, contents).await?)
}
+
+ /// Check if a file or directory exists at the given relative path within the space.
+ pub async fn exists(&self, relative_path: impl AsRef<Path>) -> Result<bool, SpaceError> {
+ let path = self.local_path(relative_path)?;
+ Ok(tokio::fs::try_exists(path).await?)
+ }
}
impl<T: SpaceRoot> From<T> for Space<T> {
diff --git a/systems/workspace/src/workspace/manager.rs b/systems/workspace/src/workspace/manager.rs
index 58eb409..fef36ab 100644
--- a/systems/workspace/src/workspace/manager.rs
+++ b/systems/workspace/src/workspace/manager.rs
@@ -7,7 +7,7 @@ pub mod id_aliases;
pub mod sheet_state;
pub struct WorkspaceManager {
- space: Space<Workspace>,
+ pub(crate) space: Space<Workspace>,
}
impl WorkspaceManager {
diff --git a/systems/workspace/src/workspace/manager/sheet_state.rs b/systems/workspace/src/workspace/manager/sheet_state.rs
index 5603adf..b7cd4fd 100644
--- a/systems/workspace/src/workspace/manager/sheet_state.rs
+++ b/systems/workspace/src/workspace/manager/sheet_state.rs
@@ -1,12 +1,17 @@
use std::path::PathBuf;
-use crate::workspace::manager::WorkspaceManager;
+use crate::workspace::manager::{WorkspaceManager, sheet_state::error::MakeSheetError};
use asset_system::asset::ReadOnlyAsset;
-use constants::workspace::files::{workspace_file_current_sheet, workspace_file_sheet};
+use constants::workspace::{
+ dirs::workspace_dir_local_sheets,
+ files::{workspace_file_current_sheet, workspace_file_sheet},
+};
use framework::space::error::SpaceError;
use just_fmt::snake_case;
use sheet_system::sheet::{Sheet, SheetData};
+pub mod error;
+
impl WorkspaceManager {
/// Read the name of the currently active Sheet
pub async fn using_sheet_name(&self) -> Result<Option<String>, SpaceError> {
@@ -25,17 +30,17 @@ impl WorkspaceManager {
}
/// Set the name of the currently active Sheet
- pub async fn edit_using_sheet_name(&self, name: &str) -> Result<(), SpaceError> {
+ pub async fn edit_using_sheet_name(&self, name: impl AsRef<str>) -> Result<(), SpaceError> {
self.space
- .write(workspace_file_current_sheet(), name.as_bytes())
+ .write(workspace_file_current_sheet(), name.as_ref().as_bytes())
.await
}
/// Read a sheet from the workspace space by name
///
/// Simple read of Sheet data, no disk write operations involved
- pub async fn read_sheet(&self, sheet_name: &str) -> Option<Sheet> {
- let sheet_name = snake_case!(sheet_name);
+ pub async fn read_sheet(&self, sheet_name: impl AsRef<str>) -> Option<Sheet> {
+ let sheet_name = snake_case!(sheet_name.as_ref());
let sheet_path = self.get_sheet_path(&sheet_name);
let mut sheet_data = SheetData::empty();
@@ -51,8 +56,11 @@ impl WorkspaceManager {
/// Get a resource pointing to local Sheet data by name
///
/// Can be used to load content, edit, and transactionally write
- pub fn get_sheet_data_asset(&self, sheet_name: &str) -> Option<ReadOnlyAsset<SheetData>> {
- let sheet_name = snake_case!(sheet_name);
+ pub fn get_sheet_data_asset(
+ &self,
+ sheet_name: impl AsRef<str>,
+ ) -> Option<ReadOnlyAsset<SheetData>> {
+ let sheet_name = snake_case!(sheet_name.as_ref());
let sheet_path = self.get_sheet_path(&sheet_name);
if sheet_path.exists() {
return Some(sheet_path.into());
@@ -70,4 +78,47 @@ impl WorkspaceManager {
// execution should not continue, so we unwrap()
.unwrap()
}
+
+ /// Get the names of all sheets in the workspace
+ pub async fn list_sheet_names(&self) -> Vec<String> {
+ let mut sheet_names = Vec::new();
+ if let Ok(mut read_dir) = self.space.read_dir(workspace_dir_local_sheets()).await {
+ while let Some(entry) = read_dir.next_entry().await.ok().flatten() {
+ let path = entry.path();
+ if path.is_file() {
+ if let Some(file_name) = path.file_stem() {
+ if let Some(name_str) = file_name.to_str() {
+ sheet_names.push(name_str.to_string());
+ }
+ }
+ }
+ }
+ }
+ sheet_names
+ }
+
+ /// Create a new sheet in the workspace by name
+ pub async fn make_sheet(&self, sheet_name: impl AsRef<str>) -> Result<(), MakeSheetError> {
+ let sheet_dir = workspace_dir_local_sheets();
+ let sheet_path = workspace_file_sheet(sheet_name.as_ref());
+ if self.space.exists(&sheet_path).await? {
+ return Err(MakeSheetError::SheetAlreadyExists);
+ }
+ self.space.create_dir_all(&sheet_dir).await?;
+ self.space
+ .write(sheet_path, SheetData::empty().as_bytes())
+ .await?;
+
+ Ok(())
+ }
+
+ /// Delete a sheet from the workspace by name
+ pub async fn drop_sheet(&self, sheet_name: impl AsRef<str>) -> Result<(), MakeSheetError> {
+ let sheet_path = workspace_file_sheet(sheet_name.as_ref());
+ if !self.space.exists(&sheet_path).await? {
+ return Err(MakeSheetError::SheetNotFound);
+ }
+ self.space.remove_file(sheet_path).await?;
+ Ok(())
+ }
}
diff --git a/systems/workspace/src/workspace/manager/sheet_state/error.rs b/systems/workspace/src/workspace/manager/sheet_state/error.rs
new file mode 100644
index 0000000..465431f
--- /dev/null
+++ b/systems/workspace/src/workspace/manager/sheet_state/error.rs
@@ -0,0 +1,29 @@
+use framework::space::error::SpaceError;
+
+#[derive(thiserror::Error, Debug)]
+pub enum MakeSheetError {
+ #[error("Sheet already exists")]
+ SheetAlreadyExists,
+
+ #[error("Sheet not found")]
+ SheetNotFound,
+
+ #[error("IO error: {0}")]
+ Io(#[from] std::io::Error),
+
+ #[error("Other error: {0}")]
+ Other(String),
+}
+
+impl From<SpaceError> for MakeSheetError {
+ fn from(value: SpaceError) -> Self {
+ match value {
+ SpaceError::SpaceNotFound => Self::SheetNotFound,
+ SpaceError::PathFormatError(path_format_error) => {
+ Self::Other(format!("PathFormatError: {}", path_format_error))
+ }
+ SpaceError::Io(error) => Self::Io(error),
+ SpaceError::Other(msg) => Self::Other(msg),
+ }
+ }
+}