diff options
| -rw-r--r-- | locales/help_docs/en.yml | 40 | ||||
| -rw-r--r-- | locales/help_docs/zh-CN.yml | 38 | ||||
| -rw-r--r-- | scripts/completion_jv.sh | 57 | ||||
| -rw-r--r-- | src/bin/jv.rs | 159 |
4 files changed, 280 insertions, 14 deletions
diff --git a/locales/help_docs/en.yml b/locales/help_docs/en.yml index f46b6ab..70e8044 100644 --- a/locales/help_docs/en.yml +++ b/locales/help_docs/en.yml @@ -266,11 +266,19 @@ jv: jv sheet make <SHEET_NAME> - Create a new sheet for yourself jv sheet drop <SHEET_NAME> - Drop the sheet for others to use - **Align struct**: - jv sheet align --list - View all items that need alignment - jv sheet align [local/remote] - All based on local or remote location - jv sheet align <ALIGN_TASK> [local/remote] - Choose based on local or remote location - jv sheet align - Manually specify alignment method + **Align**: + jv sheet align - View all items that need alignment + + For moved items: + jv sheet align <ITEM> [local/remote] - Align specified moved item + jv sheet align moved [local/remote] - Align all moved items + + For lost items: + jv sheet align <ITEM> <CREATED_ITEM> - Point to created item to confirm move + jv sheet align <ITEM> confirm - Confirm this file is lost + jv sheet align lost confirm - Confirm all lost items + + jv sheet align --work - Use editor mode to align files Sheets are core concepts in JustEnoughVCS, each sheet represents an independent file collection. You can switch work between different sheets, or export files from one sheet to another. @@ -483,6 +491,16 @@ jv: from_core: | **Error**: `%{err}` (This error is from core call) + sheet: + align: + no_direction: | + Cannot confirm alignment direction! + **Tip**: Use local or remote to indicate whether you want to keep local or remote paths + + align_item_not_found: | + Cannot find this alignment item! + **Tip**: Use `jv align` to view available alignment items + account: no_user_dir: Cannot find user directory! add: Failed to add account `%{account}`, please check if the account already exists. @@ -595,6 +613,18 @@ jv: tip_no_sheet: | You don't have any sheets, you can use `jv make <SHEET_NAME>` to create a new sheet + align: + list: | + Your local workspace has the following alignment tasks pending: + %{tasks} + + task_name: TASK + local_path: LOCAL_FILE + remote_path: REMOTE_FILE + + no_changes: | + Great, there are no struct changes in the local workspace! + docs: list: header: | diff --git a/locales/help_docs/zh-CN.yml b/locales/help_docs/zh-CN.yml index 4a7daf4..fab838d 100644 --- a/locales/help_docs/zh-CN.yml +++ b/locales/help_docs/zh-CN.yml @@ -258,10 +258,18 @@ jv: jv sheet drop <表名称> - 将表抛弃,以供其他人使用 **对齐**: - jv sheet align --list - 查看所有需要对齐的项目 - jv sheet align [local/remote] - 全部基于本地位置或远程位置 - jv sheet align <对齐任务> [local/remote] - 选择基于本地位置或远程位置 - jv sheet align - 手动指定对齐方式 + jv sheet align tasks - 查看所有需要对齐的项 + + 对于移动项: + jv sheet align <项> [local/remote] - 对齐指定移动项 + jv sheet align moved [local/remote] - 对齐所有移动项 + + 对于丢失项: + jv sheet align <项> <创建项> - 指向创建项,以确认移动 + jv sheet align <项> confirm - 确认该文件已丢失 + jv sheet align lost confirm - 确认所有丢失项 + + jv sheet align --work - 使用编辑器模式对齐文件 表是 JustEnoughVCS 中的核心概念,每个表代表一块独立的文件集合 您可以在不同的表之间切换工作,或者将文件从一张表导出到另一张表 @@ -484,6 +492,16 @@ jv: from_core: | **错误**:`%{err}`(该错误来自核心调用) + sheet: + align: + no_direction: | + 无法确认对齐的方向! + **提示**:使用 local 或 remote 来表示您要保留本地或远程的路径 + + align_item_not_found: | + 无法找到该对齐项! + **提示**:使用 `jv align` 查看可用对齐项 + account: no_user_dir: 无法找到用户目录! add: 添加账户 `%{account}` 失败,请检查账户是否已存在。 @@ -602,6 +620,18 @@ jv: **没有可以编辑的表!** 您没有任何一张表,可使用 `jv make <表名>` 创建一张新表 + align: + list: | + 您的本地工作区有如下变更待处理: + %{tasks} + + task_name: 项名称 + local_path: 本地文件 + remote_path: 远程文件 + + no_changes: | + 很好,本地工作区并没有结构变更! + docs: list: header: | diff --git a/scripts/completion_jv.sh b/scripts/completion_jv.sh index 43c8f70..ff600ed 100644 --- a/scripts/completion_jv.sh +++ b/scripts/completion_jv.sh @@ -25,10 +25,10 @@ _jv_completion() { local account_commands="list as add remove movekey mvkey mvk genpub help" # Subcommands - Sheet - local sheet_commands="list use exit make drop help" + local sheet_commands="list use exit make drop help align" # Subcommands - Sheet - local sheet_commands="list use exit make drop help" + local sheet_commands="list use exit make drop help align" # Completion subcommands if [[ $cword -eq 1 ]]; then @@ -97,10 +97,63 @@ _jv_completion() { COMPREPLY=($(compgen -W "$all_sheets" -- "$cur")) fi ;; + "align") + if [[ $cword -eq 3 ]]; then + local align_items="lost moved" + local unsolved_items + unsolved_items=$($cmd sheet align --unsolved --raw 2>/dev/null) + COMPREPLY=($(compgen -W "$align_items $unsolved_items" -- "$cur")) + elif [[ $cword -eq 4 ]]; then + local item="${words[3]}" + local align_operations="" + local created_items + created_items=$($cmd sheet align --created --raw 2>/dev/null) + + if [[ "$item" == "lost" ]]; then + align_operations="confirm" + elif [[ "$item" == lost:* ]]; then + align_operations="confirm $created_items" + elif [[ "$item" == "moved" || "$item" == moved:* ]]; then + align_operations="local remote" + else + align_operations="local remote confirm $created_items" + fi + + COMPREPLY=($(compgen -W "$align_operations" -- "$cur")) + fi + ;; esac return 0 fi + # Completion align + if [[ "$subcmd" == "align" ]]; then + if [[ $cword -eq 2 ]]; then + local align_items="lost moved" + local unsolved_items + unsolved_items=$($cmd sheet align --unsolved --raw 2>/dev/null) + COMPREPLY=($(compgen -W "$align_items $unsolved_items" -- "$cur")) + elif [[ $cword -eq 3 ]]; then + local item="${words[2]}" + local align_operations="" + local created_items + created_items=$($cmd sheet align --created --raw 2>/dev/null) + + if [[ "$item" == "lost" ]]; then + align_operations="confirm" + elif [[ "$item" == lost:* ]]; then + align_operations="confirm $created_items" + elif [[ "$item" == "moved" || "$item" == moved:* ]]; then + align_operations="local remote" + else + align_operations="local remote confirm $created_items" + fi + + COMPREPLY=($(compgen -W "$align_operations" -- "$cur")) + fi + return 0 + fi + # Completion login if [[ "$subcmd" == "login" ]]; then if [[ $cword -eq 2 ]]; then diff --git a/src/bin/jv.rs b/src/bin/jv.rs index 06215f2..22edf95 100644 --- a/src/bin/jv.rs +++ b/src/bin/jv.rs @@ -24,13 +24,13 @@ use just_enough_vcs::{ }, }, constants::{ - CLIENT_FILE_WORKSPACE, CLIENT_FOLDER_WORKSPACE_ROOT_NAME, CLIENT_PATH_WORKSPACE_ROOT, - PORT, REF_SHEET_NAME, + CLIENT_FILE_TODOLIST, CLIENT_FILE_WORKSPACE, CLIENT_FOLDER_WORKSPACE_ROOT_NAME, + CLIENT_PATH_WORKSPACE_ROOT, PORT, REF_SHEET_NAME, }, current::{current_doc_dir, current_local_path}, data::{ local::{ - LocalWorkspace, cached_sheet::CachedSheet, config::LocalConfig, + LocalWorkspace, align::AlignTasks, cached_sheet::CachedSheet, config::LocalConfig, file_status::AnalyzeResult, latest_file_data::LatestFileData, latest_info::LatestInfo, local_files::get_relative_paths, }, @@ -176,6 +176,9 @@ enum JustEnoughVcsWorkspaceCommand { /// List all accounts Accounts, + /// Align file structure + Align(SheetAlignArgs), + /// Set current local workspace account As(SetLocalWorkspaceAccountArgs), @@ -255,6 +258,9 @@ enum SheetManage { /// Drop current sheet Drop(SheetDropArgs), + + /// Align file structure + Align(SheetAlignArgs), } #[derive(Parser, Debug)] @@ -318,6 +324,39 @@ struct SheetDropArgs { } #[derive(Parser, Debug)] +struct SheetAlignArgs { + /// Show help information + #[arg(short, long)] + help: bool, + + /// Align task + task: Option<String>, + + /// Align operation + to: Option<String>, + + /// List Option: All + #[arg(long = "all")] + list_all: bool, + + /// List Option: Unsolved + #[arg(long = "unsolved")] + list_unsolved: bool, + + /// List Option: Created + #[arg(long = "created")] + list_created: bool, + + /// Editor mode + #[arg(short, long)] + work: bool, + + /// Show raw output (for list) + #[arg(short, long)] + raw: bool, +} + +#[derive(Parser, Debug)] struct LoginArgs { /// Show help information #[arg(short, long)] @@ -804,6 +843,7 @@ async fn main() { SheetManage::Exit(sheet_exit_args) => jv_sheet_exit(sheet_exit_args).await, SheetManage::Make(sheet_make_args) => jv_sheet_make(sheet_make_args).await, SheetManage::Drop(sheet_drop_args) => jv_sheet_drop(sheet_drop_args).await, + SheetManage::Align(sheet_align_args) => jv_sheet_align(sheet_align_args).await, }, JustEnoughVcsWorkspaceCommand::Track(track_file_args) => { if track_file_args.help { @@ -912,6 +952,9 @@ async fn main() { ) .await } + JustEnoughVcsWorkspaceCommand::Align(sheet_align_args) => { + jv_sheet_align(sheet_align_args).await + } JustEnoughVcsWorkspaceCommand::As(args) => { let user_dir = match UserDirectory::current_doc_dir() { Some(dir) => dir, @@ -1910,6 +1953,116 @@ async fn jv_sheet_drop(args: SheetDropArgs) { } } +async fn jv_sheet_align(args: SheetAlignArgs) { + let Some(local_dir) = current_local_path() else { + eprintln!("{}", md(t!("jv.fail.workspace_not_found")).trim()); + return; + }; + + let Ok(local_cfg) = LocalConfig::read_from(local_dir.join(CLIENT_FILE_WORKSPACE)).await else { + eprintln!("{}", md(t!("jv.fail.read_cfg"))); + return; + }; + let Some(local_workspace) = LocalWorkspace::init_current_dir(local_cfg) else { + eprintln!("{}", md(t!("jv.fail.workspace_not_found")).trim()); + return; + }; + + let Ok(analyzed) = AnalyzeResult::analyze_local_status(&local_workspace).await else { + eprintln!("{}", md(t!("jv.fail.status.analyze")).trim()); + return; + }; + + let align_tasks = AlignTasks::from_analyze_result(analyzed); + + // No task input, list mode + let Some(task) = args.task else { + // Raw output + if args.raw { + if args.list_all { + align_tasks.created.iter().for_each(|i| println!("{}", i.0)); + align_tasks.moved.iter().for_each(|i| println!("{}", i.0)); + align_tasks.lost.iter().for_each(|i| println!("{}", i.0)); + return; + } + if args.list_created { + align_tasks.created.iter().for_each(|i| println!("{}", i.0)); + return; + } + if args.list_unsolved { + align_tasks.moved.iter().for_each(|i| println!("{}", i.0)); + align_tasks.lost.iter().for_each(|i| println!("{}", i.0)); + return; + } + return; + } + + let mut table = SimpleTable::new(vec![ + t!("jv.success.sheet.align.task_name").to_string(), + t!("jv.success.sheet.align.local_path").to_string(), + if !align_tasks.moved.is_empty() { + t!("jv.success.sheet.align.remote_path").to_string() + } else { + "".to_string() + }, + ]); + + let mut empty_count = 0; + + if !align_tasks.created.is_empty() { + align_tasks.created.iter().for_each(|(n, p)| { + table.push_item(vec![ + format!("+ {}", n).green().to_string(), + p.display().to_string().green().to_string(), + "".to_string(), + ]); + }); + } else { + empty_count += 1; + } + + if !align_tasks.lost.is_empty() { + align_tasks.lost.iter().for_each(|(n, p)| { + table.push_item(vec![ + format!("- {}", n).red().to_string(), + p.display().to_string().red().to_string(), + "".to_string(), + ]); + }); + } else { + empty_count += 1; + } + + if !align_tasks.moved.is_empty() { + align_tasks.moved.iter().for_each(|(n, (rp, lp))| { + table.push_item(vec![ + format!("> {}", n).yellow().to_string(), + lp.display().to_string().yellow().to_string(), + rp.display().to_string(), + ]); + }); + } else { + empty_count += 1; + } + + if empty_count == 3 { + println!("{}", md(t!("jv.success.sheet.align.no_changes").trim())); + } else { + println!( + "{}", + md(t!("jv.success.sheet.align.list", tasks = table.to_string())) + ); + } + + return; + }; + + let Some(to) = args.to else { + eprintln!("{}", md(t!("jv.fail.sheet.align.no_direction"))); + return; + }; +} + async fn jv_track(args: TrackFileArgs) { let track_files = if let Some(files) = args.track_files.clone() { files |
