summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE-MIT2
-rw-r--r--resources/helpdoc/Welcome_To_JVCS.en.md2
-rw-r--r--resources/helpdoc/Welcome_To_JVCS.zh-CN.md2
-rw-r--r--resources/helpdoc/commands/hexdump.en.md2
-rw-r--r--resources/helpdoc/commands/hexdump.zh-CN.md2
-rw-r--r--resources/helpdoc/commands/sheetdump.en.md2
-rw-r--r--resources/helpdoc/commands/sheetdump.zh-CN.md2
-rw-r--r--resources/helpdoc/commands/sheetedit.en.md2
-rw-r--r--resources/helpdoc/commands/sheetedit.zh-CN.md2
-rw-r--r--resources/locales/jvn/helpdoc_viewer/en.yml1
-rw-r--r--resources/locales/jvn/helpdoc_viewer/zh-CN.yml1
-rw-r--r--src/systems/helpdoc/helpdoc_viewer.rs96
-rw-r--r--utils/src/display.rs1
-rw-r--r--utils/src/display/str_width.rs18
-rw-r--r--utils/src/display/table.rs21
15 files changed, 88 insertions, 68 deletions
diff --git a/LICENSE-MIT b/LICENSE-MIT
index 5cc333b..e90df8f 100644
--- a/LICENSE-MIT
+++ b/LICENSE-MIT
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2025 JustEnoughVCS Team, Weicao-CatilGrass
+Copyright (c) 2026 JustEnoughVCS Team, Weicao-CatilGrass
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/resources/helpdoc/Welcome_To_JVCS.en.md b/resources/helpdoc/Welcome_To_JVCS.en.md
index f82f58e..8161371 100644
--- a/resources/helpdoc/Welcome_To_JVCS.en.md
+++ b/resources/helpdoc/Welcome_To_JVCS.en.md
@@ -1 +1 @@
-# Welcome
+> Welcome to the `JustEnoughVCS` CLI program!
diff --git a/resources/helpdoc/Welcome_To_JVCS.zh-CN.md b/resources/helpdoc/Welcome_To_JVCS.zh-CN.md
index 2dfd3ee..a67c5b0 100644
--- a/resources/helpdoc/Welcome_To_JVCS.zh-CN.md
+++ b/resources/helpdoc/Welcome_To_JVCS.zh-CN.md
@@ -1 +1 @@
-# 你好
+> 欢迎使用 `JustEnoughVCS` 命令行程序!
diff --git a/resources/helpdoc/commands/hexdump.en.md b/resources/helpdoc/commands/hexdump.en.md
index 60d5275..4d30df1 100644
--- a/resources/helpdoc/commands/hexdump.en.md
+++ b/resources/helpdoc/commands/hexdump.en.md
@@ -1,5 +1,3 @@
-# Hexdump
-
> Print binary information
## Usage
diff --git a/resources/helpdoc/commands/hexdump.zh-CN.md b/resources/helpdoc/commands/hexdump.zh-CN.md
index 9b5b8ad..cbc743f 100644
--- a/resources/helpdoc/commands/hexdump.zh-CN.md
+++ b/resources/helpdoc/commands/hexdump.zh-CN.md
@@ -1,5 +1,3 @@
-# Hexdump
-
> 打印二进制信息
## 使用
diff --git a/resources/helpdoc/commands/sheetdump.en.md b/resources/helpdoc/commands/sheetdump.en.md
index 1616f12..63be56b 100644
--- a/resources/helpdoc/commands/sheetdump.en.md
+++ b/resources/helpdoc/commands/sheetdump.en.md
@@ -1,5 +1,3 @@
-# Sheetdump
-
> Visually output the internal structure of a `Sheet`
## Usage
diff --git a/resources/helpdoc/commands/sheetdump.zh-CN.md b/resources/helpdoc/commands/sheetdump.zh-CN.md
index 0ae46ef..e1a827f 100644
--- a/resources/helpdoc/commands/sheetdump.zh-CN.md
+++ b/resources/helpdoc/commands/sheetdump.zh-CN.md
@@ -1,5 +1,3 @@
-# Sheetdump
-
> 可视化地输出 `Sheet` 的内部结构
## 使用
diff --git a/resources/helpdoc/commands/sheetedit.en.md b/resources/helpdoc/commands/sheetedit.en.md
index 80f2a7b..2a161dd 100644
--- a/resources/helpdoc/commands/sheetedit.en.md
+++ b/resources/helpdoc/commands/sheetedit.en.md
@@ -1,5 +1,3 @@
-# Sheetedit
-
> Edit `Sheet` files using your system editor
## Usage
diff --git a/resources/helpdoc/commands/sheetedit.zh-CN.md b/resources/helpdoc/commands/sheetedit.zh-CN.md
index f30825a..b94ee34 100644
--- a/resources/helpdoc/commands/sheetedit.zh-CN.md
+++ b/resources/helpdoc/commands/sheetedit.zh-CN.md
@@ -1,5 +1,3 @@
-# Sheetedit
-
> 使用系统编辑器修改 `Sheet` 文件
## 使用
diff --git a/resources/locales/jvn/helpdoc_viewer/en.yml b/resources/locales/jvn/helpdoc_viewer/en.yml
index 1f5d9d4..78acae4 100644
--- a/resources/locales/jvn/helpdoc_viewer/en.yml
+++ b/resources/locales/jvn/helpdoc_viewer/en.yml
@@ -1,4 +1,5 @@
helpdoc_viewer:
+ title: JustEnoughVCS Help Documents
tree_area_hint: |
_List_ | ↑↓: Page | ←→/Space: Switch view | Q: Quit
content_area_hint: |
diff --git a/resources/locales/jvn/helpdoc_viewer/zh-CN.yml b/resources/locales/jvn/helpdoc_viewer/zh-CN.yml
index 65825d5..1c169c9 100644
--- a/resources/locales/jvn/helpdoc_viewer/zh-CN.yml
+++ b/resources/locales/jvn/helpdoc_viewer/zh-CN.yml
@@ -1,4 +1,5 @@
helpdoc_viewer:
+ title: JustEnoughVCS 帮助文档
tree_area_hint: |
_列表_ | ↑↓: 翻页 | ←→/Space: 切换视图 | Q: 退出
content_area_hint: |
diff --git a/src/systems/helpdoc/helpdoc_viewer.rs b/src/systems/helpdoc/helpdoc_viewer.rs
index 1968775..8473ce1 100644
--- a/src/systems/helpdoc/helpdoc_viewer.rs
+++ b/src/systems/helpdoc/helpdoc_viewer.rs
@@ -16,6 +16,8 @@ use std::{
io::{Write, stdout},
};
+const TREE_WIDTH: u16 = 25;
+
struct HelpdocViewer {
/// Current language
lang: String,
@@ -193,6 +195,49 @@ impl HelpdocViewer {
formatted.lines().map(|s| s.to_string()).collect()
}
+ /// Truncate a string containing ANSI escape sequences, preserving ANSI sequences
+ fn truncate_with_ansi(text: &str, max_width: usize) -> String {
+ let mut result = String::new();
+ let mut current_width = 0;
+ let mut chars = text.chars().peekable();
+ let mut in_ansi_escape = false;
+ let mut ansi_buffer = String::new();
+
+ while let Some(c) = chars.next() {
+ if c == '\x1b' {
+ ansi_buffer.push(c);
+ while let Some(&next_c) = chars.peek() {
+ ansi_buffer.push(next_c);
+ chars.next();
+
+ if next_c.is_ascii_alphabetic() {
+ break;
+ }
+ }
+
+ result.push_str(&ansi_buffer);
+ ansi_buffer.clear();
+ in_ansi_escape = false;
+ continue;
+ }
+
+ if in_ansi_escape {
+ ansi_buffer.push(c);
+ continue;
+ }
+
+ let char_width = if c.is_ascii() { 1 } else { 2 };
+ if current_width + char_width > max_width {
+ break;
+ }
+
+ result.push(c);
+ current_width += char_width;
+ }
+
+ result
+ }
+
/// Run viewer
async fn run(&mut self) -> std::io::Result<()> {
enable_raw_mode()?;
@@ -218,17 +263,14 @@ impl HelpdocViewer {
/// Draw interface
fn draw(&self) -> std::io::Result<()> {
+ let tree_width = TREE_WIDTH;
let (width, height) = crossterm::terminal::size()?;
- if height <= 3 {
- let content = self.current_doc_content();
- println!("{}", content);
+ if height <= 3 || width <= tree_width {
return Ok(());
}
execute!(stdout(), Clear(ClearType::All))?;
-
- let tree_width = 25;
let content_width = width - tree_width - 1;
// Draw title
@@ -236,7 +278,7 @@ impl HelpdocViewer {
stdout(),
MoveTo(0, 0),
SetForegroundColor(Color::Cyan),
- Print(format!("JVCS Help Docs - {}", self.lang)),
+ Print(format!("{} - {}", t!("helpdoc_viewer.title"), self.lang)),
ResetColor
)?;
@@ -309,7 +351,7 @@ impl HelpdocViewer {
// If this is the currently selected document, highlight it (white background, black text)
let is_selected = node.path == self.current_doc;
- if is_selected {
+ if is_selected && self.focus == FocusArea::Tree {
// Highlight with white background and black text
execute!(
stdout(),
@@ -359,11 +401,18 @@ impl HelpdocViewer {
/// Draw content area
fn draw_content(&self, x: u16, y: u16, width: u16, height: u16) -> std::io::Result<()> {
// Draw content area title
+ let (fg_color, bg_color) = if self.focus == FocusArea::Content {
+ (Color::Black, Color::White)
+ } else {
+ (Color::Yellow, Color::Black)
+ };
+
execute!(
stdout(),
MoveTo(x, y - 1),
- SetForegroundColor(Color::Yellow),
- Print(format!("> {}", self.current_doc)),
+ SetForegroundColor(fg_color),
+ SetBackgroundColor(bg_color),
+ Print(format!(" Reading `{}` ", self.current_doc)),
ResetColor
)?;
@@ -384,26 +433,9 @@ impl HelpdocViewer {
.skip(start_line)
{
let line_y = y + i as u16 - start_line as u16;
- let display_line = if line.len() > width as usize {
- let mut end = width as usize;
- while end > 0 && !line.is_char_boundary(end) {
- end -= 1;
- }
- if end == 0 {
- // If the first character is multi-byte, display at least one character
- let mut end = 1;
- while end < line.len() && !line.is_char_boundary(end) {
- end += 1;
- }
- &line[..end]
- } else {
- &line[..end]
- }
- } else {
- line
- };
+ let display_line = Self::truncate_with_ansi(line, width as usize);
- execute!(stdout(), MoveTo(x, line_y), Print(display_line))?;
+ execute!(stdout(), MoveTo(x, line_y), Print(&display_line))?;
}
// Display scroll position indicator
@@ -445,12 +477,8 @@ impl HelpdocViewer {
}
.to_string();
- let truncated_text = if status_text.len() > width as usize {
- &status_text[..width as usize]
- } else {
- &status_text
- };
- execute!(stdout(), Print(truncated_text))?;
+ let truncated_text = Self::truncate_with_ansi(&status_text, width as usize);
+ execute!(stdout(), Print(&truncated_text))?;
execute!(stdout(), ResetColor)?;
Ok(())
diff --git a/utils/src/display.rs b/utils/src/display.rs
index 5b452ce..c2ffeea 100644
--- a/utils/src/display.rs
+++ b/utils/src/display.rs
@@ -1,3 +1,4 @@
pub mod markdown;
pub mod pager;
+pub mod str_width;
pub mod table;
diff --git a/utils/src/display/str_width.rs b/utils/src/display/str_width.rs
new file mode 100644
index 0000000..a725bdb
--- /dev/null
+++ b/utils/src/display/str_width.rs
@@ -0,0 +1,18 @@
+pub fn display_width(s: &str) -> usize {
+ // Filter out ANSI escape sequences before calculating width
+ let filtered_bytes = strip_ansi_escapes::strip(s);
+ let filtered_str = match std::str::from_utf8(&filtered_bytes) {
+ Ok(s) => s,
+ Err(_) => s, // Fallback to original string if UTF-8 conversion fails
+ };
+
+ let mut width = 0;
+ for c in filtered_str.chars() {
+ if c.is_ascii() {
+ width += 1;
+ } else {
+ width += 2;
+ }
+ }
+ width
+}
diff --git a/utils/src/display/table.rs b/utils/src/display/table.rs
index ae745d8..e6f1aca 100644
--- a/utils/src/display/table.rs
+++ b/utils/src/display/table.rs
@@ -1,3 +1,5 @@
+use crate::display::str_width::display_width;
+
pub struct Table {
items: Vec<String>,
line: Vec<Vec<String>>,
@@ -122,22 +124,3 @@ impl std::fmt::Display for Table {
Ok(())
}
}
-
-pub fn display_width(s: &str) -> usize {
- // Filter out ANSI escape sequences before calculating width
- let filtered_bytes = strip_ansi_escapes::strip(s);
- let filtered_str = match std::str::from_utf8(&filtered_bytes) {
- Ok(s) => s,
- Err(_) => s, // Fallback to original string if UTF-8 conversion fails
- };
-
- let mut width = 0;
- for c in filtered_str.chars() {
- if c.is_ascii() {
- width += 1;
- } else {
- width += 2;
- }
- }
- width
-}