From 89eb19bcbb6f56778d58ad5710ff83feecf2da9b Mon Sep 17 00:00:00 2001 From: Weicao-CatilGrass <1992414357@qq.com> Date: Tue, 9 Dec 2025 21:45:25 +0800 Subject: Fix duplicate input issue on Windows with IME handling Add Windows-specific input filtering to prevent duplicate key events and handle IME composition properly. Skip key release events, detect duplicate events within 20ms window, and filter IME control characters. --- src/bin/jvii.rs | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 127 insertions(+), 3 deletions(-) diff --git a/src/bin/jvii.rs b/src/bin/jvii.rs index aacd371..83d6162 100644 --- a/src/bin/jvii.rs +++ b/src/bin/jvii.rs @@ -2,12 +2,13 @@ use std::env; use std::fs; use std::io::{self, Write}; use std::path::PathBuf; +use std::time::{Duration, Instant}; use clap::{Parser, command}; use crossterm::{ QueueableCommand, cursor::MoveTo, - event::{self, Event, KeyCode, KeyEvent, KeyModifiers}, + event::{self, Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers}, execute, style::{self, Color, Print, SetForegroundColor}, terminal::{ @@ -46,6 +47,10 @@ struct Editor { modified: bool, terminal_size: (u16, u16), should_exit: bool, + #[cfg(windows)] + last_key_event: Option<(KeyCode, KeyModifiers, Instant)>, + #[cfg(windows)] + ime_composing: bool, } impl Editor { @@ -53,7 +58,7 @@ impl Editor { let content = if file_path.exists() { fs::read_to_string(&file_path)? .lines() - .map(|s| s.to_string()) + .map(|line| line.to_string()) .collect() } else { vec![String::new()] @@ -71,6 +76,10 @@ impl Editor { modified: false, terminal_size: (width, height), should_exit: false, + #[cfg(windows)] + last_key_event: None, + #[cfg(windows)] + ime_composing: false, }) } @@ -367,6 +376,9 @@ impl Editor { return Err(e); } + // Clear input buffer to avoid leftover keystrokes from command execution + self.clear_input_buffer()?; + // Initial render if let Err(e) = self.render(&mut stdout) { self.cleanup_terminal(&mut stdout)?; @@ -377,6 +389,25 @@ impl Editor { let result = loop { match event::read() { Ok(Event::Key(key_event)) => { + // Windows-specific input handling for IME and duplicate events + #[cfg(windows)] + { + // Skip key release events (we only care about presses) + if matches!(key_event.kind, KeyEventKind::Release) { + continue; + } + + // Handle IME composition + if self.should_skip_ime_event(&key_event) { + continue; + } + + // Skip duplicate events + if self.is_duplicate_event(&key_event) { + continue; + } + } + if let Err(e) = self.handle_key_event(key_event, &mut stdout) { break Err(e); } @@ -409,6 +440,84 @@ impl Editor { Ok(()) } + fn clear_input_buffer(&self) -> io::Result<()> { + // Try to read and discard any pending events in the buffer + while event::poll(Duration::from_millis(0))? { + let _ = event::read()?; + } + Ok(()) + } + + #[cfg(windows)] + fn is_duplicate_event(&mut self, key_event: &KeyEvent) -> bool { + let now = Instant::now(); + let current_event = (key_event.code.clone(), key_event.modifiers, now); + + // Check if this is the same event that just happened + if let Some((last_code, last_modifiers, last_time)) = &self.last_key_event { + if *last_code == key_event.code + && *last_modifiers == key_event.modifiers + && now.duration_since(*last_time) < Duration::from_millis(20) + // Reduced to 20ms for better responsiveness + { + // This is likely a duplicate event from IME or Windows input handling + return true; + } + } + + // Update last event + self.last_key_event = Some(current_event); + false + } + + #[cfg(not(windows))] + fn is_duplicate_event(&mut self, _key_event: &KeyEvent) -> bool { + false + } + + #[cfg(windows)] + fn should_skip_ime_event(&mut self, key_event: &KeyEvent) -> bool { + // Check for IME composition markers + match &key_event.code { + KeyCode::Char(c) => { + // IME composition often produces control characters or special sequences + let c_u32 = *c as u32; + + // Check for IME composition start/end markers + // Some IMEs use special characters or sequences + if c_u32 == 0x16 || c_u32 == 0x17 || c_u32 == 0x18 { + // These are common IME control characters + self.ime_composing = true; + return true; + } + + // Check for dead keys or composition characters + if c_u32 < 0x20 || (c_u32 >= 0x80 && c_u32 < 0xA0) { + // Control characters or C1 control codes + return true; + } + + // If we were composing and get a normal character, check if it's part of composition + if self.ime_composing { + // Reset composition state when we get a printable character + if c.is_ascii_graphic() || c.is_alphanumeric() { + self.ime_composing = false; + } else { + return true; + } + } + + false + } + _ => false, + } + } + + #[cfg(not(windows))] + fn should_skip_ime_event(&mut self, _key_event: &KeyEvent) -> bool { + false + } + fn handle_key_event(&mut self, key_event: KeyEvent, stdout: &mut io::Stdout) -> io::Result<()> { match key_event.code { KeyCode::Char('s') if key_event.modifiers.contains(KeyModifiers::CONTROL) => { @@ -419,6 +528,15 @@ impl Editor { self.show_message(&t!("jvii.messages.file_saved"), stdout)?; } } + KeyCode::Char('v') if key_event.modifiers.contains(KeyModifiers::CONTROL) => { + // Handle Ctrl+V paste - skip normal character insertion + // On Windows, Ctrl+V might also generate a 'v' character event + // We'll handle paste separately if needed + self.is_selecting = false; + self.selection_start = None; + // For now, just ignore Ctrl+V to prevent extra 'v' character + return Ok(()); + } KeyCode::Char(c) => { if key_event.modifiers.contains(KeyModifiers::SHIFT) { self.is_selecting = true; @@ -433,7 +551,9 @@ impl Editor { // Handle special characters match c { '\n' | '\r' => self.new_line(), - _ => self.insert_char(c), + _ => { + self.insert_char(c); + } } } KeyCode::Backspace => { @@ -518,6 +638,10 @@ async fn main() { // Init i18n set_locale(¤t_locales()); + // Windows specific initialization for colored output + #[cfg(windows)] + let _ = colored::control::set_virtual_terminal(true); + let args = JustEnoughVcsInputer::parse(); // Check if a file argument was provided -- cgit From 5fd3992ff8eea62967288c639985bfe60b9a171b Mon Sep 17 00:00:00 2001 From: Weicao-CatilGrass <1992414357@qq.com> Date: Wed, 10 Dec 2025 10:22:45 +0800 Subject: Move installation script to setup/linux directory --- README.md | 2 +- README_zh_CN.md | 2 +- scripts/inst.sh | 88 ----------------------------------------------------- setup/linux/inst.sh | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 90 deletions(-) delete mode 100644 scripts/inst.sh create mode 100644 setup/linux/inst.sh diff --git a/README.md b/README.md index 4545a99..0770896 100644 --- a/README.md +++ b/README.md @@ -20,5 +20,5 @@ ```bash # Linux -curl -s https://raw.githubusercontent.com/JustEnoughVCS/CommandLine/main/scripts/inst.sh | bash +curl -s https://raw.githubusercontent.com/JustEnoughVCS/CommandLine/main/setup/linux/inst.sh | bash ``` diff --git a/README_zh_CN.md b/README_zh_CN.md index dcd9537..e129640 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -20,5 +20,5 @@ ```bash # Linux -curl -s https://raw.githubusercontent.com/JustEnoughVCS/CommandLine/main/scripts/inst.sh | bash +curl -s https://raw.githubusercontent.com/JustEnoughVCS/CommandLine/main/setup/linux/inst.sh | bash ``` diff --git a/scripts/inst.sh b/scripts/inst.sh deleted file mode 100644 index bbebeb8..0000000 --- a/scripts/inst.sh +++ /dev/null @@ -1,88 +0,0 @@ -# Check if required tools are installed -echo "Checking for required tools..." -if ! command -v cargo &> /dev/null; then - echo "Error: cargo is not installed. Please install Rust and Cargo first." - exit 1 -fi -if ! command -v git &> /dev/null; then - echo "Error: git is not installed. Please install git first." - exit 1 -fi - -# Set installation directory to current directory -echo "Installation directory set to current directory: $(pwd)" -install_dir="$(pwd)" - -# Clone or update repos -echo "Cloning or updating repositories..." -mkdir -p "$install_dir" -cd "$install_dir" - -# Function to clone or pull repository -clone_or_pull() { - local repo_url="$1" - local repo_name=$(basename "$repo_url") - - if [ -d "$repo_name" ]; then - echo "Repository $repo_name already exists, pulling latest changes..." - cd "$repo_name" - git pull origin main - cd .. - else - echo "Cloning $repo_name..." - git clone "$repo_url" - fi -} - -# Clone or update repositories -clone_or_pull https://github.com/JustEnoughVCS/CommandLine -clone_or_pull https://github.com/JustEnoughVCS/VersionControl - -# Setup VersionControl repo -echo "Setting up VersionControl..." -cd VersionControl -chmod +x setup.sh -./setup.sh - -# Build CLI -echo "Building CLI..." -cd ../CommandLine -cargo build --release -cargo export - -# Configure shell to include CLI in PATH -echo "Now adding JustEnoughVCS CLI to your environment. Please select your target shell:" -echo "1) ~/.zshrc (Zsh)" -echo "2) ~/.bashrc (Bash)" -echo "3) ~/.config/fish/config.fish (Fish)" -echo "4) Skip shell configuration" -echo -n "Enter your choice (1-4): " -read choice - -case $choice in - 1) - config_file="$HOME/.zshrc" - ;; - 2) - config_file="$HOME/.bashrc" - ;; - 3) - config_file="$HOME/.config/fish/config.fish" - ;; - 4) - echo "Skipping shell configuration." - echo "Installation completed! You can manually add the CLI to your PATH later." - exit 0 - ;; - *) - echo "Invalid choice. Skipping shell configuration." - exit 0 - ;; -esac - -cli_path="$(pwd)/export/jv_cli.sh" -echo "# JustEnoughVCS CLI" >> "$config_file" -echo "source \"$cli_path\"" >> "$config_file" -echo "CLI has been added to $config_file" -echo "Please restart your shell or run: source $config_file" -echo "Installation completed successfully!" diff --git a/setup/linux/inst.sh b/setup/linux/inst.sh new file mode 100644 index 0000000..bbebeb8 --- /dev/null +++ b/setup/linux/inst.sh @@ -0,0 +1,88 @@ +# Check if required tools are installed +echo "Checking for required tools..." +if ! command -v cargo &> /dev/null; then + echo "Error: cargo is not installed. Please install Rust and Cargo first." + exit 1 +fi +if ! command -v git &> /dev/null; then + echo "Error: git is not installed. Please install git first." + exit 1 +fi + +# Set installation directory to current directory +echo "Installation directory set to current directory: $(pwd)" +install_dir="$(pwd)" + +# Clone or update repos +echo "Cloning or updating repositories..." +mkdir -p "$install_dir" +cd "$install_dir" + +# Function to clone or pull repository +clone_or_pull() { + local repo_url="$1" + local repo_name=$(basename "$repo_url") + + if [ -d "$repo_name" ]; then + echo "Repository $repo_name already exists, pulling latest changes..." + cd "$repo_name" + git pull origin main + cd .. + else + echo "Cloning $repo_name..." + git clone "$repo_url" + fi +} + +# Clone or update repositories +clone_or_pull https://github.com/JustEnoughVCS/CommandLine +clone_or_pull https://github.com/JustEnoughVCS/VersionControl + +# Setup VersionControl repo +echo "Setting up VersionControl..." +cd VersionControl +chmod +x setup.sh +./setup.sh + +# Build CLI +echo "Building CLI..." +cd ../CommandLine +cargo build --release +cargo export + +# Configure shell to include CLI in PATH +echo "Now adding JustEnoughVCS CLI to your environment. Please select your target shell:" +echo "1) ~/.zshrc (Zsh)" +echo "2) ~/.bashrc (Bash)" +echo "3) ~/.config/fish/config.fish (Fish)" +echo "4) Skip shell configuration" +echo -n "Enter your choice (1-4): " +read choice + +case $choice in + 1) + config_file="$HOME/.zshrc" + ;; + 2) + config_file="$HOME/.bashrc" + ;; + 3) + config_file="$HOME/.config/fish/config.fish" + ;; + 4) + echo "Skipping shell configuration." + echo "Installation completed! You can manually add the CLI to your PATH later." + exit 0 + ;; + *) + echo "Invalid choice. Skipping shell configuration." + exit 0 + ;; +esac + +cli_path="$(pwd)/export/jv_cli.sh" +echo "# JustEnoughVCS CLI" >> "$config_file" +echo "source \"$cli_path\"" >> "$config_file" +echo "CLI has been added to $config_file" +echo "Please restart your shell or run: source $config_file" +echo "Installation completed successfully!" -- cgit From 1567bab16b1eeb8ddaf5a8cc09c71bdb0bedbda3 Mon Sep 17 00:00:00 2001 From: Weicao-CatilGrass <1992414357@qq.com> Date: Wed, 10 Dec 2025 10:49:52 +0800 Subject: Add Windows installer and export scripts - Add Inno Setup configuration for Windows installer - Add PowerShell scripts for installation and uninstallation - Create Windows-specific export script - Update existing export script to suppress build output - Include application icon for installer --- docs/images/Yizi.ico | Bin 0 -> 270622 bytes export.ps1 | 13 +++++++++++++ export.sh | 4 +++- setup/windows/inst.ps1 | 8 ++++++++ setup/windows/setup_jv_cli.iss | 42 +++++++++++++++++++++++++++++++++++++++++ setup/windows/uninst.ps1 | 39 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 docs/images/Yizi.ico create mode 100644 export.ps1 create mode 100644 setup/windows/inst.ps1 create mode 100644 setup/windows/setup_jv_cli.iss create mode 100644 setup/windows/uninst.ps1 diff --git a/docs/images/Yizi.ico b/docs/images/Yizi.ico new file mode 100644 index 0000000..24a2d00 Binary files /dev/null and b/docs/images/Yizi.ico differ diff --git a/export.ps1 b/export.ps1 new file mode 100644 index 0000000..d24c37e --- /dev/null +++ b/export.ps1 @@ -0,0 +1,13 @@ +# Require : Cargo (Rust), ISCC (Inno Setup) + +# Build +cargo build --workspace --release +if ($LASTEXITCODE -ne 0) { + # Build failed +} else { + # Build succeeded + # Export + if (cargo run --manifest-path crates/build_helper/Cargo.toml --bin exporter) { + ISCC /Q .\setup\windows\setup_jv_cli.iss + } +} diff --git a/export.sh b/export.sh index 5428107..52215ba 100755 --- a/export.sh +++ b/export.sh @@ -1,7 +1,9 @@ #!/bin/bash +# Require : Cargo (Rust) + # Build -if cargo build --workspace --release; then +if cargo build --workspace --release >/dev/null 2>&1; then # Export cargo run --manifest-path crates/build_helper/Cargo.toml --bin exporter fi diff --git a/setup/windows/inst.ps1 b/setup/windows/inst.ps1 new file mode 100644 index 0000000..2e15dc3 --- /dev/null +++ b/setup/windows/inst.ps1 @@ -0,0 +1,8 @@ +. ".\uninst.ps1" + +$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path + +$parentDir = Split-Path -Parent $scriptDir +Add-Content -Path $PROFILE -Value "`n# JustEnoughVCS - Begin #" +Add-Content -Path $PROFILE -Value ". `"$parentDir\jv_cli.ps1`"" +Add-Content -Path $PROFILE -Value "# JustEnoughVCS - End #" diff --git a/setup/windows/setup_jv_cli.iss b/setup/windows/setup_jv_cli.iss new file mode 100644 index 0000000..24b2a32 --- /dev/null +++ b/setup/windows/setup_jv_cli.iss @@ -0,0 +1,42 @@ +#define MyAppName "JustEnoughVCS" +#define MyAppVersion "0.1.0" +#define MyAppPublisher "JustEnoughVCS Team" +#define MyAppURL "https://jvcs.cc/" + +[Setup] +AppId={{8265DF21-F290-487E-9403-C2730EC31A03} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +AppPublisher={#MyAppPublisher} +AppPublisherURL={#MyAppURL} +AppSupportURL={#MyAppURL} +AppUpdatesURL={#MyAppURL} +DefaultDirName={autopf}\{#MyAppName} +DefaultGroupName={#MyAppName} +AllowNoIcons=yes +LicenseFile=..\..\LICENSE +PrivilegesRequired=lowest +OutputDir=..\..\export\setup +OutputBaseFilename=JustEnoughVCS For Windows +SetupIconFile=..\..\docs\images\Yizi.ico +SolidCompression=yes +WizardStyle=modern dynamic + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" + +[Files] +Source: "..\..\export\*"; Excludes: "setup"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs +Source: "inst.ps1"; DestDir: "{app}\scripts\"; Flags: ignoreversion +Source: "uninst.ps1"; DestDir: "{app}\scripts\"; Flags: ignoreversion + +[Run] +Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{app}\scripts\inst.ps1"""; Flags: runhidden; Description: "Running post-installation script..."; StatusMsg: "Running post-installation script..."; AfterInstall: RunPostInstall + +[UninstallRun] +Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{app}\scripts\uninst.ps1"""; Flags: runhidden; RunOnceId: "UninstallScript" + +[Code] +procedure RunPostInstall; +begin +end; diff --git a/setup/windows/uninst.ps1 b/setup/windows/uninst.ps1 new file mode 100644 index 0000000..d5c898d --- /dev/null +++ b/setup/windows/uninst.ps1 @@ -0,0 +1,39 @@ +$profileContent = Get-Content $PROFILE -ErrorAction SilentlyContinue +if ($profileContent) { + $startMarker = "# JustEnoughVCS - Begin #" + $endMarker = "# JustEnoughVCS - End #" + $newContent = @() + $insideBlock = $false + $foundStart = $false + + foreach ($line in $profileContent) { + if ($line.Trim() -eq $startMarker) { + $insideBlock = $true + $foundStart = $true + continue + } + if ($line.Trim() -eq $endMarker) { + $insideBlock = $false + continue + } + if (-not $insideBlock) { + $newContent += $line + } + } + + if ($foundStart -and $insideBlock) { + $newContent = @() + $insideBlock = $false + foreach ($line in $profileContent) { + if ($line.Trim() -eq $startMarker) { + $insideBlock = $true + continue + } + if (-not $insideBlock) { + $newContent += $line + } + } + } + + $newContent | Set-Content $PROFILE +} -- cgit From be67a79c4a10fc42d7d15b87e488db00238e4676 Mon Sep 17 00:00:00 2001 From: Weicao-CatilGrass <1992414357@qq.com> Date: Wed, 10 Dec 2025 11:02:09 +0800 Subject: Rename Windows CLI installer template file --- setup/windows/setup_jv_cli.iss | 42 --------------------------------- setup/windows/setup_jv_cli_template.iss | 42 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 42 deletions(-) delete mode 100644 setup/windows/setup_jv_cli.iss create mode 100644 setup/windows/setup_jv_cli_template.iss diff --git a/setup/windows/setup_jv_cli.iss b/setup/windows/setup_jv_cli.iss deleted file mode 100644 index 24b2a32..0000000 --- a/setup/windows/setup_jv_cli.iss +++ /dev/null @@ -1,42 +0,0 @@ -#define MyAppName "JustEnoughVCS" -#define MyAppVersion "0.1.0" -#define MyAppPublisher "JustEnoughVCS Team" -#define MyAppURL "https://jvcs.cc/" - -[Setup] -AppId={{8265DF21-F290-487E-9403-C2730EC31A03} -AppName={#MyAppName} -AppVersion={#MyAppVersion} -AppPublisher={#MyAppPublisher} -AppPublisherURL={#MyAppURL} -AppSupportURL={#MyAppURL} -AppUpdatesURL={#MyAppURL} -DefaultDirName={autopf}\{#MyAppName} -DefaultGroupName={#MyAppName} -AllowNoIcons=yes -LicenseFile=..\..\LICENSE -PrivilegesRequired=lowest -OutputDir=..\..\export\setup -OutputBaseFilename=JustEnoughVCS For Windows -SetupIconFile=..\..\docs\images\Yizi.ico -SolidCompression=yes -WizardStyle=modern dynamic - -[Languages] -Name: "english"; MessagesFile: "compiler:Default.isl" - -[Files] -Source: "..\..\export\*"; Excludes: "setup"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs -Source: "inst.ps1"; DestDir: "{app}\scripts\"; Flags: ignoreversion -Source: "uninst.ps1"; DestDir: "{app}\scripts\"; Flags: ignoreversion - -[Run] -Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{app}\scripts\inst.ps1"""; Flags: runhidden; Description: "Running post-installation script..."; StatusMsg: "Running post-installation script..."; AfterInstall: RunPostInstall - -[UninstallRun] -Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{app}\scripts\uninst.ps1"""; Flags: runhidden; RunOnceId: "UninstallScript" - -[Code] -procedure RunPostInstall; -begin -end; diff --git a/setup/windows/setup_jv_cli_template.iss b/setup/windows/setup_jv_cli_template.iss new file mode 100644 index 0000000..24b2a32 --- /dev/null +++ b/setup/windows/setup_jv_cli_template.iss @@ -0,0 +1,42 @@ +#define MyAppName "JustEnoughVCS" +#define MyAppVersion "0.1.0" +#define MyAppPublisher "JustEnoughVCS Team" +#define MyAppURL "https://jvcs.cc/" + +[Setup] +AppId={{8265DF21-F290-487E-9403-C2730EC31A03} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +AppPublisher={#MyAppPublisher} +AppPublisherURL={#MyAppURL} +AppSupportURL={#MyAppURL} +AppUpdatesURL={#MyAppURL} +DefaultDirName={autopf}\{#MyAppName} +DefaultGroupName={#MyAppName} +AllowNoIcons=yes +LicenseFile=..\..\LICENSE +PrivilegesRequired=lowest +OutputDir=..\..\export\setup +OutputBaseFilename=JustEnoughVCS For Windows +SetupIconFile=..\..\docs\images\Yizi.ico +SolidCompression=yes +WizardStyle=modern dynamic + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" + +[Files] +Source: "..\..\export\*"; Excludes: "setup"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs +Source: "inst.ps1"; DestDir: "{app}\scripts\"; Flags: ignoreversion +Source: "uninst.ps1"; DestDir: "{app}\scripts\"; Flags: ignoreversion + +[Run] +Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{app}\scripts\inst.ps1"""; Flags: runhidden; Description: "Running post-installation script..."; StatusMsg: "Running post-installation script..."; AfterInstall: RunPostInstall + +[UninstallRun] +Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{app}\scripts\uninst.ps1"""; Flags: runhidden; RunOnceId: "UninstallScript" + +[Code] +procedure RunPostInstall; +begin +end; -- cgit From 15b508b7931aacd0c07ad6f52d4cefa6eef69fa1 Mon Sep 17 00:00:00 2001 From: Weicao-CatilGrass <1992414357@qq.com> Date: Wed, 10 Dec 2025 11:10:47 +0800 Subject: Add Windows installer script generation to build process - Generate Inno Setup installer script from template at build time - Extract author and homepage from Cargo.toml for script customization - Add generated installer script to .gitignore to avoid committing build artifacts --- .gitignore | 3 ++ Cargo.toml | 2 ++ build.rs | 64 +++++++++++++++++++++++++++++++++ setup/windows/setup_jv_cli_template.iss | 6 ++-- 4 files changed, 72 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index a3e2496..e00561c 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ # Compile info /src/data/compile_info.rs + +# Setup script +/setup/windows/setup_jv_cli.iss diff --git a/Cargo.toml b/Cargo.toml index 92ed9ed..524c96a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,8 @@ name = "just_enough_vcs_cli" edition = "2024" build = "build.rs" +authors = ["JustEnoughVCS Team"] +homepage = "http://jvcs.cc/" [workspace] members = ["crates/build_helper"] diff --git a/build.rs b/build.rs index 04fcd71..e215418 100644 --- a/build.rs +++ b/build.rs @@ -7,12 +7,76 @@ const COMPILE_INFO_RS_TEMPLATE: &str = "./src/data/compile_info.rs.template"; fn main() { let repo_root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); + // Only generate installer script on Windows + if cfg!(target_os = "windows") { + if let Err(e) = generate_installer_script(&repo_root) { + eprintln!("Failed to generate installer script: {}", e); + std::process::exit(1); + } + } + if let Err(e) = generate_compile_info(&repo_root) { eprintln!("Failed to generate compile info: {}", e); std::process::exit(1); } } +/// Generate Inno Setup installer script (Windows only) +fn generate_installer_script(repo_root: &PathBuf) -> Result<(), Box> { + let template_path = repo_root.join("setup/windows/setup_jv_cli_template.iss"); + let output_path = repo_root.join("setup/windows/setup_jv_cli.iss"); + + let template = std::fs::read_to_string(&template_path)?; + + let author = get_author()?; + let version = get_version(); + let site = get_site()?; + + let generated = template + .replace("<<>>", &author) + .replace("<<>>", &version) + .replace("<<>>", &site); + + std::fs::write(output_path, generated)?; + Ok(()) +} + +fn get_author() -> Result> { + let cargo_toml_path = std::path::Path::new("Cargo.toml"); + let cargo_toml_content = std::fs::read_to_string(cargo_toml_path)?; + let cargo_toml: toml::Value = toml::from_str(&cargo_toml_content)?; + + if let Some(package) = cargo_toml.get("package") { + if let Some(authors) = package.get("authors") { + if let Some(authors_array) = authors.as_array() { + if let Some(first_author) = authors_array.get(0) { + if let Some(author_str) = first_author.as_str() { + return Ok(author_str.to_string()); + } + } + } + } + } + + Err("Author not found in Cargo.toml".into()) +} + +fn get_site() -> Result> { + let cargo_toml_path = std::path::Path::new("Cargo.toml"); + let cargo_toml_content = std::fs::read_to_string(cargo_toml_path)?; + let cargo_toml: toml::Value = toml::from_str(&cargo_toml_content)?; + + if let Some(package) = cargo_toml.get("package") { + if let Some(homepage) = package.get("homepage") { + if let Some(site_str) = homepage.as_str() { + return Ok(site_str.to_string()); + } + } + } + + Err("Homepage not found in Cargo.toml".into()) +} + /// Generate compile info fn generate_compile_info(repo_root: &PathBuf) -> Result<(), Box> { // Read the template code diff --git a/setup/windows/setup_jv_cli_template.iss b/setup/windows/setup_jv_cli_template.iss index 24b2a32..124d897 100644 --- a/setup/windows/setup_jv_cli_template.iss +++ b/setup/windows/setup_jv_cli_template.iss @@ -1,7 +1,7 @@ #define MyAppName "JustEnoughVCS" -#define MyAppVersion "0.1.0" -#define MyAppPublisher "JustEnoughVCS Team" -#define MyAppURL "https://jvcs.cc/" +#define MyAppVersion "<<>>" +#define MyAppPublisher "<<>>" +#define MyAppURL "<<>>" [Setup] AppId={{8265DF21-F290-487E-9403-C2730EC31A03} -- cgit