simplify install/uninstall scripts, update README
Some checks are pending
Build & Release / Build & test (push) Waiting to run
Build & Release / Build .deb (push) Blocked by required conditions

This commit is contained in:
Khoa Vo 2026-07-01 16:35:56 +07:00
parent 7a8f409d20
commit 83c3e3d1fa
3 changed files with 115 additions and 317 deletions

View file

@ -113,39 +113,50 @@ Both **VNI** and **Telex** are fully supported. Switch via **Ctrl+LeftShift** or
## Installation ## Installation
### Build from Source ### One-Command Install (recommended)
Works on both **Linux Mint** and **Ubuntu** (including 24.04+ Wayland):
```bash ```bash
# Dependencies (Ubuntu/Debian) git clone https://github.com/vndangkhoa/vietc.git /tmp/vietc \
sudo apt install git curl build-essential pkg-config \ && cd /tmp/vietc && sudo ./install.sh
libx11-dev libxtst-dev libevdev-dev libdbus-1-dev ```
# Clone and build The script will:
1. Install build + runtime dependencies
2. Compile all binaries
3. Install to `/usr/bin/`
4. Set up uinput udev rules
5. Add your user to the `input` group
**After install:** Log out and log back in, then launch `vietc-tray` from your application menu.
### Manual Build & Run
```bash
# Install dependencies
sudo apt install git curl build-essential pkg-config \
libx11-dev libxtst-dev libevdev-dev libdbus-1-dev wl-clipboard
# Enable accessibility (Ubuntu Wayland — for password detection)
gsettings set org.gnome.desktop.a11y.applications screen-reader-enabled true
# Build
git clone https://github.com/vndangkhoa/vietc.git git clone https://github.com/vndangkhoa/vietc.git
cd vietc cd vietc
cargo build --release cargo build --release
# Add user to input group (for keyboard capture) # Run (Mint — no sudo needed for uinput)
sudo usermod -aG input $USER
# Log out and log back in
# Run
./target/release/vietc ./target/release/vietc
# Run (Ubuntu — needs sudo for keyboard grab)
sudo ./target/release/vietc
``` ```
### Wayland (Ubuntu 24.04+) — Additional steps ### Uninstall
```bash ```bash
sudo apt install wl-clipboard sudo ./uninstall.sh
gsettings set org.gnome.desktop.a11y.applications screen-reader-enabled true
```
### uinput Access (recommended)
```bash
sudo modprobe uinput
echo 'KERNEL=="uinput", GROUP="input", MODE="0660"' | sudo tee /etc/udev/rules.d/99-uinput.rules
sudo udevadm control --reload-rules && sudo udevadm trigger
``` ```
--- ---

View file

@ -3,285 +3,110 @@
# Viet+ — Vietnamese Input Method Installer # Viet+ — Vietnamese Input Method Installer
set -euo pipefail set -euo pipefail
# Color codes for output RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[0;33m'; NC='\033[0m'
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0;69m' # No Color
NC='\033[0m'
echo -e "${BLUE}=== Viet+ Installation Script ===${NC}" [ "$EUID" -ne 0 ] && echo -e "${RED}Please run with sudo.${NC}" && exit 1
# Check for root privilege requirement echo -e "${GREEN}=== Viet+ Installer ===${NC}"
check_root() {
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}Error: This script must be run as root (or with sudo) to install system files and update permissions.${NC}"
echo -e "Please re-run as: ${YELLOW}sudo $0${NC}"
exit 1
fi
}
# Detect distribution # Detect distro
detect_distro() { [ -f /etc/os-release ] && . /etc/os-release
if [ -f /etc/os-release ]; then DISTRO="${ID:-unknown}"
. /etc/os-release echo "Detected: $DISTRO"
DISTRO=$ID
DISTRO_LIKE=${ID_LIKE:-""}
else
echo -e "${RED}Error: Cannot detect Linux distribution (/etc/os-release missing).${NC}"
exit 1
fi
echo -e "Detected OS: ${GREEN}${DISTRO}${NC}"
}
# Install dependencies using package manager # Install dependencies
install_dependencies() { install_deps() {
local mode=$1 # "build" or "run"
echo -e "Installing ${mode} dependencies..."
case "$DISTRO" in case "$DISTRO" in
ubuntu|debian|raspbian|pop|mint|linuxmint|neon|zorin|elementary) ubuntu|debian|linuxmint|mint|pop|neon|zorin|elementary)
export DEBIAN_FRONTEND=noninteractive export DEBIAN_FRONTEND=noninteractive
apt-get update -y apt-get update -y
if [ "$mode" = "build" ]; then apt-get install -y build-essential pkg-config libx11-dev libxtst-dev \
apt-get install -y build-essential pkg-config libx11-dev libxtst-dev libdbus-1-dev libevdev-dev libwayland-dev curl libdbus-1-dev libevdev-dev curl git
fi apt-get install -y libevdev2 libdbus-1-3 libx11-6 libxtst6 xclip wl-clipboard
apt-get install -y libevdev2 libdbus-1-3 libx11-6 libxtst6 xclip wl-clipboard libwayland-client0 curl
;; ;;
fedora|rhel|centos) fedora|rhel|centos)
if [ "$mode" = "build" ]; then dnf install -y gcc pkgconfig libX11-devel libXtst-devel dbus-devel libevdev-devel curl git
dnf install -y gcc pkgconfig libX11-devel libXtst-devel dbus-devel libevdev-devel
fi
dnf install -y libevdev libX11 libXtst dbus-libs xclip wl-clipboard dnf install -y libevdev libX11 libXtst dbus-libs xclip wl-clipboard
;; ;;
arch|manjaro|arco) arch|manjaro)
if [ "$mode" = "build" ]; then pacman -Sy --needed --noconfirm base-devel pkgconf libx11 libxtst dbus libevdev curl git
pacman -Sy --needed --noconfirm base-devel pkgconf libx11 libxtst dbus libevdev
fi
pacman -Sy --needed --noconfirm libevdev libx11 libxtst dbus xclip wl-clipboard pacman -Sy --needed --noconfirm libevdev libx11 libxtst dbus xclip wl-clipboard
;; ;;
*) *)
if [[ "$DISTRO_LIKE" == *"ubuntu"* || "$DISTRO_LIKE" == *"debian"* ]]; then echo -e "${YELLOW}Unsupported: $DISTRO. Install deps manually.${NC}"
export DEBIAN_FRONTEND=noninteractive
apt-get update -y
if [ "$mode" = "build" ]; then
apt-get install -y build-essential pkg-config libx11-dev libxtst-dev libdbus-1-dev libevdev-dev libwayland-dev curl
fi
apt-get install -y libevdev2 libdbus-1-3 libx11-6 libxtst6 xclip wl-clipboard libwayland-client0 curl
else
echo -e "${YELLOW}Warning: Unsupported distribution '${DISTRO}'. Please make sure you have the following packages installed manually:${NC}"
echo -e " - libevdev, libdbus-1, libx11, libxtst, xclip, wl-clipboard"
if [ "$mode" = "build" ]; then
echo -e " - gcc, pkg-config, and development headers for the above libraries."
fi
fi
;; ;;
esac esac
} }
# Check for Rust compiler (needed only for source build) install_deps
check_rust() {
if [ -n "${SUDO_USER:-}" ]; then
local user_home
user_home="$(getent passwd "$SUDO_USER" 2>/dev/null | cut -d: -f6 || echo "/home/$SUDO_USER")"
export CARGO_HOME="$user_home/.cargo"
export RUSTUP_HOME="$user_home/.rustup"
export PATH="$CARGO_HOME/bin:$PATH"
fi
if ! command -v cargo >/dev/null 2>&1; then # Install Rust if missing
echo -e "${YELLOW}Rust toolchain not found.${NC}" if ! command -v cargo &>/dev/null; then
read -p "Would you like to install Rust toolchain now? [Y/n] " -n 1 -r echo "Installing Rust..."
echo curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
if [[ $REPLY =~ ^[Nn]$ ]]; then export PATH="$HOME/.cargo/bin:$PATH"
echo -e "${RED}Error: Cargo is required to build from source.${NC}"
exit 1
fi
echo "Installing Rust via rustup.rs..."
# Run rustup installer as the original non-root user if SUDO_USER is set
if [ -n "${SUDO_USER:-}" ]; then
su - "$SUDO_USER" -c "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y"
else
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
export PATH="$HOME/.cargo/bin:$PATH"
fi
fi
echo -e "Rust version: ${GREEN}$(rustc --version)${NC}"
}
# Determine if we are installing from source tree or prebuilt binaries
check_root # Need root to perform OS checks and dependencies install
detect_distro
SOURCE_DIR=""
if [ -f "./Cargo.toml" ] && [ -d "./engine" ] && [ -d "./ui" ]; then
SOURCE_DIR=$(pwd)
echo -e "Status: Running from ${GREEN}Source Tree${NC}"
else
echo -e "Status: Running from ${GREEN}Release Package${NC}"
fi fi
# 1. Compile or Stage Binaries # Kill old processes
if [ -n "$SOURCE_DIR" ]; then
install_dependencies "build"
check_rust
echo -e "=== Compiling Viet+ ==="
# Build core components
cargo build --release
# Build UI
(cd ui && cargo build --release)
# Compile C helper
gcc -O2 -o target/release/vietc-xrecord packaging/deb/vietc-xrecord.c -lX11 -lXtst
BIN_DAEMON="target/release/vietc"
BIN_CLI="target/release/vietc-cli"
BIN_UINPUTD="target/release/vietc-uinputd"
BIN_TRAY="ui/target/release/vietc-tray"
BIN_XRECORD="target/release/vietc-xrecord"
FILE_RULES="packaging/99-vietc.rules"
FILE_DESKTOP="packaging/deb/vietc.desktop"
FILE_CONFIG="vietc.toml"
DIR_ICONS="packaging/icons"
else
# Install from prebuilt release folder
install_dependencies "run"
BIN_DAEMON="bin/vietc-daemon"
BIN_CLI="bin/vietc-cli"
BIN_UINPUTD="bin/vietc-uinputd"
BIN_TRAY="bin/vietc-tray"
BIN_XRECORD="bin/vietc-xrecord"
FILE_RULES="udev/99-vietc.rules"
FILE_DESKTOP="desktop/vietc.desktop"
FILE_CONFIG="config/config.toml"
DIR_ICONS="icons"
# Validation
if [ ! -f "$BIN_DAEMON" ] && [ -f "bin/vietc" ]; then
BIN_DAEMON="bin/vietc" # Fallback if not renamed in build
fi
fi
# Kill running instances before installing new files
echo "Stopping any running Viet+ processes..."
pkill -x vietc-tray 2>/dev/null || true pkill -x vietc-tray 2>/dev/null || true
pkill -x vietc-daemon 2>/dev/null || true pkill -x vietc-daemon 2>/dev/null || true
pkill -x vietc-uinputd 2>/dev/null || true
pkill -x vietc 2>/dev/null || true pkill -x vietc 2>/dev/null || true
# 2. Install Binaries # Build
echo "Installing binaries to /usr/bin/..." echo "Building..."
cp "$BIN_DAEMON" /usr/bin/vietc-daemon cargo build --release
cp "$BIN_CLI" /usr/bin/ (cd ui && cargo build --release)
cp "$BIN_UINPUTD" /usr/bin/ if command -v gcc &>/dev/null && [ -f packaging/deb/vietc-xrecord.c ]; then
cp "$BIN_TRAY" /usr/bin/ gcc -O2 -o target/release/vietc-xrecord packaging/deb/vietc-xrecord.c -lX11 -lXtst 2>/dev/null || true
cp "$BIN_XRECORD" /usr/bin/
chmod 755 /usr/bin/vietc-daemon /usr/bin/vietc-cli /usr/bin/vietc-uinputd /usr/bin/vietc-tray /usr/bin/vietc-xrecord
# Remove old local path binaries to prevent shadows
rm -f /usr/local/bin/vietc-tray /usr/local/bin/vietc /usr/local/bin/vietc-daemon \
/usr/local/bin/vietc-cli /usr/local/bin/vietc-uinputd /usr/local/bin/vietc-xrecord 2>/dev/null || true
# 3. Install Icons
echo "Installing icons..."
mkdir -p /usr/share/icons/hicolor/256x256/apps
cp "$DIR_ICONS/vietc.svg" /usr/share/icons/hicolor/256x256/apps/
cp "$DIR_ICONS/vietc-vn.svg" /usr/share/icons/hicolor/256x256/apps/
cp "$DIR_ICONS/vietc-en.svg" /usr/share/icons/hicolor/256x256/apps/
if command -v gtk-update-icon-cache >/dev/null 2>&1; then
gtk-update-icon-cache -f /usr/share/icons/hicolor/ >/dev/null 2>&1 || true
fi fi
# 4. Install Desktop File # Install binaries
echo "Installing desktop launcher..." echo "Installing to /usr/bin/..."
mkdir -p /usr/share/applications cp target/release/vietc /usr/bin/vietc-daemon
cp "$FILE_DESKTOP" /usr/share/applications/ cp target/release/vietc-cli /usr/bin/
cp target/release/vietc-uinputd /usr/bin/
cp ui/target/release/vietc-tray /usr/bin/
[ -f target/release/vietc-xrecord ] && cp target/release/vietc-xrecord /usr/bin/
chmod 755 /usr/bin/vietc-daemon /usr/bin/vietc-cli /usr/bin/vietc-uinputd /usr/bin/vietc-tray 2>/dev/null || true
if command -v update-desktop-database >/dev/null 2>&1; then # Clean old /usr/local/bin/ binaries
update-desktop-database /usr/share/applications >/dev/null 2>&1 || true rm -f /usr/local/bin/vietc /usr/local/bin/vietc-daemon /usr/local/bin/vietc-cli \
fi /usr/local/bin/vietc-uinputd /usr/local/bin/vietc-tray /usr/local/bin/vietc-xrecord 2>/dev/null || true
# 5. Install Systemd User Service # Udev rules for uinput
echo "Installing systemd user service..." echo 'KERNEL=="uinput", GROUP="input", MODE="0660"' > /etc/udev/rules.d/99-vietc.rules
mkdir -p /usr/lib/systemd/user udevadm control --reload-rules 2>/dev/null || true
cat > /usr/lib/systemd/user/vietc.service << 'SERVICE' udevadm trigger 2>/dev/null || true
[Unit]
Description=Viet+ Vietnamese IME Tray
PartOf=graphical-session.target
[Service] # User setup
Type=simple INSTALLING_USER="${SUDO_USER:-$USER}"
ExecStart=/usr/bin/vietc-tray
Restart=on-failure
RestartSec=5
[Install]
WantedBy=default.target
SERVICE
# 6. Install XDG Autostart
echo "Setting up autostart..."
mkdir -p /etc/xdg/autostart
cat > /etc/xdg/autostart/vietc-tray.desktop << 'AUTOSTART'
[Desktop Entry]
Type=Application
Name=Viet+ Tray
Comment=Vietnamese Input Method Tray
Exec=vietc-tray
Icon=vietc
Terminal=false
Categories=Utility;
StartupNotify=false
NoDisplay=true
AUTOSTART
# 7. Install default config
echo "Installing default configuration..."
mkdir -p /etc/vietc
cp "$FILE_CONFIG" /etc/vietc/config.toml
chmod 644 /etc/vietc/config.toml
# 8. Configure permissions (uinput)
echo "Installing udev rules for uinput access..."
mkdir -p /etc/udev/rules.d
cp "$FILE_RULES" /etc/udev/rules.d/99-vietc.rules
chmod 644 /etc/udev/rules.d/99-vietc.rules
echo "Reloading udev rules..."
if command -v udevadm >/dev/null 2>&1; then
udevadm control --reload-rules >/dev/null 2>&1 || true
udevadm trigger --subsystem-match=misc >/dev/null 2>&1 || true
fi
# Add active users to input group
INSTALLING_USER="${SUDO_USER:-${USER:-}}"
if [ -n "$INSTALLING_USER" ] && [ "$INSTALLING_USER" != "root" ]; then if [ -n "$INSTALLING_USER" ] && [ "$INSTALLING_USER" != "root" ]; then
echo "Adding user '$INSTALLING_USER' to group 'input'..." adduser "$INSTALLING_USER" input 2>/dev/null || true
if ! groups "$INSTALLING_USER" 2>/dev/null | grep -qw input; then rm -f "$(getent passwd "$INSTALLING_USER" | cut -d: -f6)/.config/vietc/config.toml" 2>/dev/null || true
if command -v usermod >/dev/null 2>&1; then
usermod -aG input "$INSTALLING_USER" || true
elif command -v adduser >/dev/null 2>&1; then
adduser "$INSTALLING_USER" input || true
fi
fi
# Remove any old conflicting configurations in user home
user_home="$(getent passwd "$INSTALLING_USER" 2>/dev/null | cut -d: -f6 || true)"
if [ -n "$user_home" ]; then
rm -f "$user_home/.config/vietc/config.toml" 2>/dev/null || true
rm -f "$user_home/.config/vietc/overrides.toml" 2>/dev/null || true
rm -f "$user_home/.config/vietc/.first-launch-done" 2>/dev/null || true
fi
fi fi
if command -v systemctl >/dev/null 2>&1; then # Create default config
systemctl --global daemon-reload >/dev/null 2>&1 || true mkdir -p /etc/vietc
fi cat > /etc/vietc/config.toml << 'EOF'
input_method = "vni"
toggle_key = "space"
toggle_method_key = "shift"
start_enabled = true
grab = true
echo -e "\n${GREEN}=== Installation Completed Successfully! ===${NC}" [password_detection]
echo -e "Please ${YELLOW}LOG OUT and LOG BACK IN${NC} to activate group permissions." enabled = true
echo -e "Once logged back in, you can start Viet+ from your application launcher menu." check_atspi2 = true
check_window_title = true
title_keywords = ["password", "passphrase", "secret", "mặt khẩu", "sudo"]
password_apps = ["pinentry", "pinentry-gtk-2", "pinentry-qt", "kwallet"]
[app_state]
enabled = true
english_apps = ["code", "vim"]
vietnamese_apps = ["telegram", "discord", "firefox"]
bypass_apps = ["kitty", "alacritty", "steam"]
EOF
echo -e "${GREEN}=== Done! ===${NC}"
echo -e "${YELLOW}Log out and log back in, then run: vietc-tray${NC}"

View file

@ -3,60 +3,22 @@
# Viet+ — Vietnamese Input Method Uninstaller # Viet+ — Vietnamese Input Method Uninstaller
set -euo pipefail set -euo pipefail
# Color codes for output RED='\033[0;31m'; GREEN='\033[0;32m'; NC='\033[0m'
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
echo -e "${RED}=== Viet+ Uninstallation Script ===${NC}" [ "$EUID" -ne 0 ] && echo -e "${RED}Please run with sudo.${NC}" && exit 1
if [ "$EUID" -ne 0 ]; then echo -e "${RED}=== Viet+ Uninstaller ===${NC}"
echo -e "${RED}Error: This script must be run as root (or with sudo).${NC}"
exit 1
fi
echo "Stopping any running Viet+ processes..."
pkill -x vietc-tray 2>/dev/null || true pkill -x vietc-tray 2>/dev/null || true
pkill -x vietc-daemon 2>/dev/null || true pkill -x vietc-daemon 2>/dev/null || true
pkill -x vietc-uinputd 2>/dev/null || true
pkill -x vietc 2>/dev/null || true pkill -x vietc 2>/dev/null || true
echo "Removing binaries..." rm -f /usr/bin/vietc-daemon /usr/bin/vietc-cli /usr/bin/vietc-uinputd \
rm -f /usr/bin/vietc-daemon /usr/bin/vietc-cli /usr/bin/vietc-uinputd /usr/bin/vietc-tray /usr/bin/vietc-xrecord /usr/bin/vietc-tray /usr/bin/vietc-xrecord
rm -f /usr/local/bin/vietc-daemon /usr/local/bin/vietc-cli /usr/local/bin/vietc-uinputd /usr/local/bin/vietc-tray /usr/local/bin/vietc-xrecord /usr/local/bin/vietc rm -f /usr/local/bin/vietc /usr/local/bin/vietc-daemon /usr/local/bin/vietc-cli \
/usr/local/bin/vietc-uinputd /usr/local/bin/vietc-tray /usr/local/bin/vietc-xrecord
echo "Removing icons..."
rm -f /usr/share/icons/hicolor/256x256/apps/vietc.svg
rm -f /usr/share/icons/hicolor/256x256/apps/vietc-vn.svg
rm -f /usr/share/icons/hicolor/256x256/apps/vietc-en.svg
if command -v gtk-update-icon-cache >/dev/null 2>&1; then
gtk-update-icon-cache -f /usr/share/icons/hicolor/ >/dev/null 2>&1 || true
fi
echo "Removing desktop files and autostart..."
rm -f /usr/share/applications/vietc.desktop
rm -f /etc/xdg/autostart/vietc-tray.desktop
if command -v update-desktop-database >/dev/null 2>&1; then
update-desktop-database /usr/share/applications >/dev/null 2>&1 || true
fi
echo "Removing systemd service..."
rm -f /usr/lib/systemd/user/vietc.service
echo "Removing udev rules..."
rm -f /etc/udev/rules.d/99-vietc.rules rm -f /etc/udev/rules.d/99-vietc.rules
if command -v udevadm >/dev/null 2>&1; then rm -f /etc/vietc/config.toml
udevadm control --reload-rules >/dev/null 2>&1 || true rmdir /etc/vietc 2>/dev/null || true
udevadm trigger --subsystem-match=misc >/dev/null 2>&1 || true
fi
echo "Removing global configuration..." echo -e "${GREEN}=== Done! ===${NC}"
rm -rf /etc/vietc
if command -v systemctl >/dev/null 2>&1; then
systemctl --global daemon-reload >/dev/null 2>&1 || true
fi
echo -e "\n${GREEN}=== Uninstallation Completed Successfully! ===${NC}"