diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-02-27 06:43:08 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-02-27 06:43:08 +0800 |
| commit | 84b004a421000c776f1009687562a47533d6cff7 (patch) | |
| tree | 39b6643003e19c231e280dd3ae57f4dd98351a76 | |
| parent | 33c3965dd84d37c7170ab7193b7d268abe57aabd (diff) | |
Add sheetedit command for editing sheet files
| -rw-r--r-- | resources/locales/jvn/cmds/sheetedit/en.yml | 22 | ||||
| -rw-r--r-- | resources/locales/jvn/cmds/sheetedit/zh-CN.yml | 21 | ||||
| -rw-r--r-- | src/cmds/arg/sheetedit.rs | 11 | ||||
| -rw-r--r-- | src/cmds/cmd/sheetedit.rs | 122 | ||||
| -rw-r--r-- | src/cmds/in/sheetedit.rs | 6 |
5 files changed, 182 insertions, 0 deletions
diff --git a/resources/locales/jvn/cmds/sheetedit/en.yml b/resources/locales/jvn/cmds/sheetedit/en.yml new file mode 100644 index 0000000..8a439d2 --- /dev/null +++ b/resources/locales/jvn/cmds/sheetedit/en.yml @@ -0,0 +1,22 @@ +sheetedit: + editor: | + # Editing `%{file_dir}` + + # Index format: + # Upstream: id/ver + # Local: ~id/ver + + # Forward format: + # Latest Version: "Mapping" => "ID/VER" + # RefSheet Version: "Mapping" => "ID/VER" => "ref" + # Specific Version: "Mapping" == "ID/VER" + # Or: "Mapping" => "ID/VER" == "VER" + + %{info} + + # TIPS: After editing, save file and exit editor. + # It will be automatically written to the original file. + + mapping: Mapping + index_source: Index + forward: Forward diff --git a/resources/locales/jvn/cmds/sheetedit/zh-CN.yml b/resources/locales/jvn/cmds/sheetedit/zh-CN.yml new file mode 100644 index 0000000..6352d36 --- /dev/null +++ b/resources/locales/jvn/cmds/sheetedit/zh-CN.yml @@ -0,0 +1,21 @@ +sheetedit: + editor: | + # 正在编辑 `%{file_dir}` + + # 索引源格式: + # 本地命名空间索引:~id/ver + # 上游命名空间索引: id/ver + + # 前方格式: + # 指向最新版本:"Mapping" => "ID/VER" + # 指向参考版本:"Mapping" => "ID/VER" => "ref" + # 指向指定版本:"Mapping" == "ID/VER" + # 或者:"Mapping" => "ID/VER" == "VER" + + %{info} + + # 完成编辑后,保存文件并退出编辑器,将会自动写入到原始文件 + + mapping: 映射地址 + index_source: 索引源 + forward: 前方 diff --git a/src/cmds/arg/sheetedit.rs b/src/cmds/arg/sheetedit.rs new file mode 100644 index 0000000..6232ef7 --- /dev/null +++ b/src/cmds/arg/sheetedit.rs @@ -0,0 +1,11 @@ +use std::path::PathBuf; + +use clap::Parser; + +#[derive(Parser, Debug)] +pub struct JVSheeteditArgument { + pub file: PathBuf, + + #[arg(short, long)] + pub editor: Option<String>, +} diff --git a/src/cmds/cmd/sheetedit.rs b/src/cmds/cmd/sheetedit.rs new file mode 100644 index 0000000..3e61642 --- /dev/null +++ b/src/cmds/cmd/sheetedit.rs @@ -0,0 +1,122 @@ +use crate::{ + cmd_output, + cmds::{ + arg::sheetedit::JVSheeteditArgument, collect::single_file::JVSingleFileCollect, + r#in::sheetedit::JVSheeteditInput, out::none::JVNoneOutput, + }, + systems::cmd::{ + cmd_system::JVCommandContext, + errors::{CmdExecuteError, CmdPrepareError}, + }, +}; +use cli_utils::{ + display::SimpleTable, env::get_default_editor, input::input_with_editor_cutsom, string_vec, +}; +use cmd_system_macros::exec; +use just_enough_vcs::system::sheet_system::{mapping::LocalMapping, sheet::SheetData}; +use just_fmt::fmt_path::{PathFormatError, fmt_path}; +use rust_i18n::t; +use std::{any::TypeId, borrow::Cow, path::PathBuf}; +use tokio::fs::create_dir_all; + +pub struct JVSheeteditCommand; +type Cmd = JVSheeteditCommand; +type Arg = JVSheeteditArgument; +type In = JVSheeteditInput; +type Collect = JVSingleFileCollect; + +fn help_str() -> String { + todo!() +} + +async fn prepare(args: &Arg, _ctx: &JVCommandContext) -> Result<In, CmdPrepareError> { + let file = fmt_path(args.file.clone()).map_err(|e| match e { + PathFormatError::InvalidUtf8(e) => CmdPrepareError::Error(e.to_string()), + })?; + let editor = args.editor.clone().unwrap_or(get_default_editor().await); + + Ok(In { file, editor }) +} + +async fn collect(args: &Arg, _ctx: &JVCommandContext) -> Result<Collect, CmdPrepareError> { + let data = match tokio::fs::read(&args.file).await { + Ok(d) => d, + Err(_) => Vec::new(), + }; + Ok(Collect { data }) +} + +#[exec] +async fn exec( + input: In, + collect: Collect, +) -> Result<(Box<dyn std::any::Any + Send + 'static>, TypeId), CmdExecuteError> { + let sheet = SheetData::try_from(collect.data).unwrap_or(SheetData::empty()); + + let mappings = sheet.mappings(); + let mut mappings_vec = mappings.iter().cloned().collect::<Vec<LocalMapping>>(); + mappings_vec.sort(); + + let template = build_template(&input.file, mappings_vec).to_string(); + + let temp_file = input.file.with_added_extension("md"); + create_dir_all(temp_file.parent().unwrap()).await?; + + let edit_result = input_with_editor_cutsom(template, &temp_file, "#", input.editor).await; + + match edit_result { + Ok(t) => { + let rebuild_sheet_data = SheetData::try_from(t.as_str()) + .map_err(|e| CmdExecuteError::Error(e.to_string()))?; + tokio::fs::write(&input.file, rebuild_sheet_data.as_bytes()).await?; + } + Err(e) => return Err(CmdExecuteError::Error(e.to_string())), + } + + cmd_output!(JVNoneOutput => JVNoneOutput {}) +} + +fn build_template(file: &PathBuf, mappings: Vec<LocalMapping>) -> Cow<'static, str> { + let mapping_table = render_pretty_mappings(&mappings); + let template = t!( + "sheetedit.editor", + file_dir = file.display(), + info = mapping_table + ); + + template +} + +fn render_pretty_mappings(mappings: &Vec<LocalMapping>) -> String { + let header = string_vec![ + format!("# {}", t!("sheetedit.mapping")), + "", + t!("sheetedit.index_source"), + "", + t!("sheetedit.forward") + ]; + + let mut simple_table = SimpleTable::new(header); + + for mapping in mappings { + let mapping_str = mapping + .to_string() + .split(" ") + .into_iter() + .map(|s| s.to_string()) + .collect::<Vec<String>>(); + simple_table.push_item(vec![ + format!( + " {} ", + mapping_str.get(0).unwrap_or(&String::default()) + ), // Mapping + format!("{} ", mapping_str.get(1).unwrap_or(&String::default())), // => & == + format!("{} ", mapping_str.get(2).unwrap_or(&String::default())), // Index + format!("{} ", mapping_str.get(3).unwrap_or(&String::default())), // => & == + format!("{} ", mapping_str.get(4).unwrap_or(&String::default())), // Forward + ]); + } + simple_table.to_string() +} + +crate::command_template!(); diff --git a/src/cmds/in/sheetedit.rs b/src/cmds/in/sheetedit.rs new file mode 100644 index 0000000..b469580 --- /dev/null +++ b/src/cmds/in/sheetedit.rs @@ -0,0 +1,6 @@ +use std::path::PathBuf; + +pub struct JVSheeteditInput { + pub file: PathBuf, + pub editor: String, +} |
