Add terminal support for *nix

This commit is contained in:
Damien Elmes 2025-06-22 21:52:44 +07:00
parent d2f818fad2
commit b250a2f724
3 changed files with 87 additions and 27 deletions

View file

@ -1,9 +1,15 @@
#!/bin/bash
#
# This script currently only supports universal builds on x86_64.
#
set -e
# Add Linux cross-compilation target
rustup target add aarch64-unknown-linux-gnu
# Detect host architecture
HOST_ARCH=$(uname -m)
# Define output paths
OUTPUT_DIR="../../../out/launcher"
@ -12,11 +18,18 @@ LAUNCHER_DIR="$OUTPUT_DIR/anki-launcher"
# Clean existing output directory
rm -rf "$LAUNCHER_DIR"
# Build binaries for both Linux architectures
cargo build -p launcher --release --target x86_64-unknown-linux-gnu
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \
# Build binaries based on host architecture
if [ "$HOST_ARCH" = "aarch64" ]; then
# On aarch64 host, only build for aarch64
cargo build -p launcher --release --target aarch64-unknown-linux-gnu
(cd ../../.. && ./ninja extract:uv_lin_arm)
else
# On other hosts, build for both architectures
cargo build -p launcher --release --target x86_64-unknown-linux-gnu
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \
cargo build -p launcher --release --target aarch64-unknown-linux-gnu
# Extract uv_lin_arm for cross-compilation
(cd ../../.. && ./ninja extract:uv_lin_arm)
fi
# Create output directory
mkdir -p "$LAUNCHER_DIR"
@ -24,13 +37,21 @@ mkdir -p "$LAUNCHER_DIR"
# Copy binaries and support files
TARGET_DIR=${CARGO_TARGET_DIR:-../../../target}
# Copy launcher binaries with architecture suffixes
cp "$TARGET_DIR/x86_64-unknown-linux-gnu/release/launcher" "$LAUNCHER_DIR/launcher.amd64"
cp "$TARGET_DIR/aarch64-unknown-linux-gnu/release/launcher" "$LAUNCHER_DIR/launcher.arm64"
# Copy uv binaries with architecture suffixes
cp "../../../out/extracted/uv/uv" "$LAUNCHER_DIR/uv.amd64"
cp "../../../out/extracted/uv_lin_arm/uv" "$LAUNCHER_DIR/uv.arm64"
# Copy binaries with architecture suffixes
if [ "$HOST_ARCH" = "aarch64" ]; then
# On aarch64 host, copy arm64 binary to both locations
cp "$TARGET_DIR/aarch64-unknown-linux-gnu/release/launcher" "$LAUNCHER_DIR/launcher.amd64"
cp "$TARGET_DIR/aarch64-unknown-linux-gnu/release/launcher" "$LAUNCHER_DIR/launcher.arm64"
# Copy uv binary to both locations
cp "../../../out/extracted/uv/uv" "$LAUNCHER_DIR/uv.amd64"
cp "../../../out/extracted/uv/uv" "$LAUNCHER_DIR/uv.arm64"
else
# On other hosts, copy architecture-specific binaries
cp "$TARGET_DIR/x86_64-unknown-linux-gnu/release/launcher" "$LAUNCHER_DIR/launcher.amd64"
cp "$TARGET_DIR/aarch64-unknown-linux-gnu/release/launcher" "$LAUNCHER_DIR/launcher.arm64"
cp "../../../out/extracted/uv/uv" "$LAUNCHER_DIR/uv.amd64"
cp "../../../out/extracted/uv_lin_arm/uv" "$LAUNCHER_DIR/uv.arm64"
fi
# Copy support files from lin directory
for file in README.md anki.1 anki.desktop anki.png anki.xml anki.xpm install.sh uninstall.sh anki; do

View file

@ -15,6 +15,7 @@ use anyhow::Result;
// Re-export Unix functions that macOS uses
pub use super::unix::{
ensure_terminal_shown,
exec_anki,
get_anki_binary_path,
initial_terminal_setup,
@ -36,20 +37,7 @@ pub fn launch_anki_detached(anki_bin: &std::path::Path, _config: &crate::Config)
Ok(())
}
pub fn ensure_terminal_shown() -> Result<()> {
let stdout_is_terminal = std::io::IsTerminal::is_terminal(&std::io::stdout());
if !stdout_is_terminal {
// If launched from GUI, relaunch in Terminal.app
relaunch_in_terminal()?;
}
// Set terminal title to "Anki Launcher"
print!("\x1b]0;Anki Launcher\x07");
Ok(())
}
fn relaunch_in_terminal() -> Result<()> {
pub fn relaunch_in_terminal() -> Result<()> {
let current_exe = std::env::current_exe().context("Failed to get current executable path")?;
Command::new("open")
.args(["-a", "Terminal"])

View file

@ -3,6 +3,7 @@
#![allow(dead_code)]
use std::io::IsTerminal;
use std::path::PathBuf;
use std::process::Command;
@ -17,8 +18,58 @@ pub fn initial_terminal_setup(_config: &mut Config) {
}
pub fn ensure_terminal_shown() -> Result<()> {
// Skip terminal relaunch on non-macOS Unix systems as we don't know which
// terminal is installed
let stdout_is_terminal = IsTerminal::is_terminal(&std::io::stdout());
if !stdout_is_terminal {
// If launched from GUI, try to relaunch in a terminal
crate::platform::relaunch_in_terminal()?;
}
// Set terminal title to "Anki Launcher"
print!("\x1b]2;Anki Launcher\x07");
Ok(())
}
#[cfg(not(target_os = "macos"))]
pub fn relaunch_in_terminal() -> Result<()> {
let current_exe = std::env::current_exe().context("Failed to get current executable path")?;
// Try terminals in order of preference
let terminals = [
("x-terminal-emulator", vec!["-e"]),
("gnome-terminal", vec!["--"]),
("konsole", vec!["-e"]),
("xfce4-terminal", vec!["-e"]),
("alacritty", vec!["-e"]),
("kitty", vec![]),
("foot", vec![]),
("urxvt", vec!["-e"]),
("xterm", vec!["-e"]),
];
for (terminal_cmd, args) in &terminals {
// Check if terminal exists
if Command::new("which")
.arg(terminal_cmd)
.output()
.map(|o| o.status.success())
.unwrap_or(false)
{
// Try to launch the terminal
let mut cmd = Command::new(terminal_cmd);
if args.is_empty() {
cmd.arg(&current_exe);
} else {
cmd.args(args).arg(&current_exe);
}
if cmd.spawn().is_ok() {
std::process::exit(0);
}
}
}
// If no terminal worked, continue without relaunching
Ok(())
}