From f4ec67f6141508a705070b81451cd1a88dd0d381 Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Fri, 20 Mar 2026 20:06:52 +0700 Subject: [PATCH 1/8] feat: Add interactive installer component to provide dynamic installation instructions for various distributions and environments. --- components.d.ts | 5 + src/components/InteractiveInstaller.vue | 836 ++++++++++++++++++++++++ src/views/Home.vue | 452 +------------ 3 files changed, 849 insertions(+), 444 deletions(-) create mode 100644 src/components/InteractiveInstaller.vue diff --git a/components.d.ts b/components.d.ts index c3c4cbf..99f276a 100644 --- a/components.d.ts +++ b/components.d.ts @@ -15,12 +15,17 @@ declare module 'vue' { ElAvatar: typeof import('element-plus/es')['ElAvatar'] ElButton: typeof import('element-plus/es')['ElButton'] ElIcon: typeof import('element-plus/es')['ElIcon'] + ElOption: typeof import('element-plus/es')['ElOption'] + ElRadioButton: typeof import('element-plus/es')['ElRadioButton'] + ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] + ElSelect: typeof import('element-plus/es')['ElSelect'] ElStep: typeof import('element-plus/es')['ElStep'] ElSteps: typeof import('element-plus/es')['ElSteps'] ElTable: typeof import('element-plus/es')['ElTable'] ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] ElTabPane: typeof import('element-plus/es')['ElTabPane'] ElTabs: typeof import('element-plus/es')['ElTabs'] + InteractiveInstaller: typeof import('./src/components/InteractiveInstaller.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] } diff --git a/src/components/InteractiveInstaller.vue b/src/components/InteractiveInstaller.vue new file mode 100644 index 0000000..fc8ee5a --- /dev/null +++ b/src/components/InteractiveInstaller.vue @@ -0,0 +1,836 @@ + + + + + diff --git a/src/views/Home.vue b/src/views/Home.vue index db19ea7..7775a5b 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -16,6 +16,7 @@ import { Aim, Brush, } from '@element-plus/icons-vue'; +import InteractiveInstaller from '../components/InteractiveInstaller.vue'; // --- STATE --- const mobileMenuOpen = ref(false); @@ -126,19 +127,6 @@ onUnmounted(() => { clearTimeout(resetTimer); }); -// --- DATA --- -interface PackageInfo { - package: string; - description: string; -} -const archPackages: PackageInfo[] = [ - { package: 'fcitx5-lotus', description: 'Build từ mã nguồn release ổn định' }, - { package: 'fcitx5-lotus-bin', description: 'Dùng binary đã build sẵn' }, - { - package: 'fcitx5-lotus-git', - description: 'Build từ danh sách commit mới nhất', - }, -]; interface SettingInfo { option: string; @@ -323,8 +311,7 @@ const copyToClipboard = async (text: string | undefined): Promise => { From 892ca3ef61d81150d6488457fd3d802d69858591 Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Fri, 20 Mar 2026 20:20:39 +0700 Subject: [PATCH 3/8] refactor: simplify installer step numbering by removing dynamic calculation and add specific alerts for auto-handled installations. --- src/components/InteractiveInstaller.vue | 78 ++++++++++++++----------- 1 file changed, 43 insertions(+), 35 deletions(-) diff --git a/src/components/InteractiveInstaller.vue b/src/components/InteractiveInstaller.vue index eb117bf..ee68c5e 100644 --- a/src/components/InteractiveInstaller.vue +++ b/src/components/InteractiveInstaller.vue @@ -131,13 +131,20 @@ const logic = { } }; -const configStepCode = computed(() => { +const activateServerCode = computed(() => { if (selectedDistro.value === 'NixOS') return '# Bước này đã được cấu hình trong flake.nix ở trên.'; - if (['Debian', 'Ubuntu'].includes(selectedDistro.value) && selectedMethod.value === 'Package Manager') { - return '# Gói .deb sẽ tự động thực hiện bước này qua post-install script.\n# Bạn có thể bỏ qua hoặc chạy lại nếu cần:\n' + serverCmd.value; + if (isAutoHandled.value) { + return '# Gói .deb sẽ tự động thực hiện bước này.\n' + serverCmd.value; } - - return `${serverCmd.value}\n\n# Thiết lập biến môi trường\n${envCmd.value}`; + return serverCmd.value; +}); + +const shellConfigCode = computed(() => { + if (selectedDistro.value === 'NixOS') return '# Bước này đã được cấu hình trong flake.nix ở trên.'; + if (isAutoHandled.value) { + return '# Gói .deb sẽ tự động thiết lập biến môi trường.\n' + envCmd.value; + } + return envCmd.value; }); const serverCmd = computed(() => { @@ -202,24 +209,6 @@ const isAutoHandled = computed(() => { return ['Debian', 'Ubuntu'].includes(selectedDistro.value) && selectedMethod.value === 'Package Manager'; }); -const getStepNumber = (stepKey: string) => { - let num = 1; // Step 1 is always visible - if (stepKey === 'install') return 1; - - if (!isAutoHandled.value) { - if (stepKey === 'activate') return 2; - if (stepKey === 'ibus') return 3; - num = 3; - } else { - num = 1; - } - - if (stepKey === 'autostart') return num + 1; - if (stepKey === 'config') return num + 2; - if (stepKey === 'extras') return num + 3; - return 0; -}; - const copyToClipboard = async (text: string) => { try { await navigator.clipboard.writeText(text); @@ -372,26 +361,45 @@ const kanataConfig = {
{{ installStepCode }}
- -
-
{{ getStepNumber('activate') }}
+
+
2
+
+

Kích hoạt Server

+
+ +
+
+
{{ activateServerCode }}
+ +
+
+
+ +
+
3
-

Kích hoạt Server & Cấu hình Shell

+

Thiết lập biến môi trường (Shell)

+
+ +
-
{{ configStepCode }}
- +
{{ shellConfigCode }}
+
- +
-
-
{{ getStepNumber('ibus') }}
+
+
4

Tắt bộ gõ cũ (IBus)

+
+ +

Nếu máy bạn đang dùng IBus, hãy tắt nó đi trước khi chuyển sang Fcitx5 để tránh xung đột.

killall ibus-daemon || ibus exit
@@ -404,7 +412,7 @@ const kanataConfig = {
-
{{ getStepNumber('autostart') }}
+
5

Tự động khởi chạy (Autostart)

@@ -414,7 +422,7 @@ const kanataConfig = {
-
{{ getStepNumber('config') }}
+
6

Cấu hình bộ gõ Fcitx5

Sau khi đã Log out và Log in lại:

@@ -425,7 +433,7 @@ const kanataConfig = {
-
{{ getStepNumber('extras') }}
+
7

Cấu hình bổ sung

From 42649edf0a6e27f46d6c6897c00c34fa9b69d4ae Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Fri, 20 Mar 2026 20:41:10 +0700 Subject: [PATCH 4/8] feat: Extract installer data and logic into a new module and import it into the interactive installer component. --- src/components/InteractiveInstaller.vue | 282 ++++++++---------------- src/data/installer.ts | 121 ++++++++++ 2 files changed, 211 insertions(+), 192 deletions(-) create mode 100644 src/data/installer.ts diff --git a/src/components/InteractiveInstaller.vue b/src/components/InteractiveInstaller.vue index ee68c5e..31e4dc9 100644 --- a/src/components/InteractiveInstaller.vue +++ b/src/components/InteractiveInstaller.vue @@ -2,134 +2,22 @@ import { ref, computed } from 'vue'; import { DocumentCopy } from '@element-plus/icons-vue'; import { ElMessage } from 'element-plus'; - -const distros = [ - { name: "Arch Linux", icon: "si-archlinux" }, - { name: "Debian", icon: "si-debian" }, - { name: "Ubuntu", icon: "si-ubuntu" }, - { name: "Fedora", icon: "si-fedora" }, - { name: "openSUSE", icon: "si-opensuse" }, - { name: "NixOS", icon: "si-nixos" } -]; -const methods = ["Package Manager", "Binary", "Source"]; -const shells = ["Bash", "Zsh", "Fish"]; -const deWms = ["GNOME", "KDE Plasma", "Xfce", "Cinnamon", "MATE", "Pantheon", "Budgie", "LXQt", "COSMIC", "i3", "Sway", "Hyprland"]; -const environments = ["X11", "Wayland"]; +import { + distros, + methods, + shells, + deWms, + environments, + logic, + fcitx5Config, + kanataConfig +} from '@/data/installer'; const selectedDistro = ref(distros[0].name); const selectedMethod = ref(methods[0]); const selectedShell = ref(shells[0]); const selectedDe = ref(deWms[0]); -const selectedEnv = ref(environments[0]); - -const logic = { - "steps": { - "install": { - "Arch Linux": { - "Package Manager": "yay -S fcitx5-lotus", - "Binary": "sudo pacman -U fcitx5-lotus-*.pkg.tar.zst", - "Source": "git clone https://github.com/LotusInputMethod/fcitx5-lotus.git\ncd fcitx5-lotus\ncmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=/usr/lib .\nmake\nsudo make install" - }, - "Debian": { - "Package Manager": "CODENAME=$(grep '^VERSION_CODENAME=' /etc/os-release | cut -d'=' -f2)\nsudo mkdir -p /etc/apt/keyrings\ncurl -fsSL https://fcitx5-lotus.pages.dev/pubkey.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/fcitx5-lotus.gpg\necho \"deb [signed-by=/etc/apt/keyrings/fcitx5-lotus.gpg] https://fcitx5-lotus.pages.dev/apt/$CODENAME $CODENAME main\" | sudo tee /etc/apt/sources.list.d/fcitx5-lotus.list\nsudo apt update && sudo apt install fcitx5-lotus", - "Binary": "sudo dpkg -i fcitx5-lotus_*.deb", - "Source": "sudo apt-get install cmake extra-cmake-modules libfcitx5core-dev libfcitx5config-dev libfcitx5utils-dev libinput-dev libudev-dev g++ golang hicolor-icon-theme pkg-config libx11-dev libfcitx5-qt6-dev qt6-base-dev fcitx5-modules-dev\ngit clone https://github.com/LotusInputMethod/fcitx5-lotus.git\ncd fcitx5-lotus\ncmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=/usr/lib .\nmake\nsudo make install" - }, - "Ubuntu": { - "Package Manager": "CODENAME=$(grep '^UBUNTU_CODENAME=' /etc/os-release | cut -d'=' -f2)\nsudo mkdir -p /etc/apt/keyrings\ncurl -fsSL https://fcitx5-lotus.pages.dev/pubkey.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/fcitx5-lotus.gpg\necho \"deb [signed-by=/etc/apt/keyrings/fcitx5-lotus.gpg] https://fcitx5-lotus.pages.dev/apt/$CODENAME $CODENAME main\" | sudo tee /etc/apt/sources.list.d/fcitx5-lotus.list\nsudo apt update && sudo apt install fcitx5-lotus", - "Binary": "sudo dpkg -i fcitx5-lotus_*.deb", - "Source": "sudo apt-get install cmake extra-cmake-modules libfcitx5core-dev libfcitx5config-dev libfcitx5utils-dev libinput-dev libudev-dev g++ golang hicolor-icon-theme pkg-config libx11-dev libfcitx5-qt6-dev qt6-base-dev fcitx5-modules-dev\ngit clone https://github.com/LotusInputMethod/fcitx5-lotus.git\ncd fcitx5-lotus\ncmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=/usr/lib .\nmake\nsudo make install" - }, - "Fedora": { - "Package Manager": "RELEASEVER=$(grep '^VERSION_ID=' /etc/os-release | cut -d'=' -f2)\nsudo rpm --import https://fcitx5-lotus.pages.dev/pubkey.gpg\nsudo dnf config-manager addrepo --from-repofile=https://fcitx5-lotus.pages.dev/rpm/fedora/fcitx5-lotus-$RELEASEVER.repo\nsudo dnf install fcitx5-lotus", - "Binary": "sudo rpm -i fcitx5-lotus-*.rpm", - "Source": "sudo dnf install cmake extra-cmake-modules fcitx5-devel libinput-devel libudev-devel gcc-c++ golang hicolor-icon-theme systemd-devel libX11-devel fcitx5-qt-devel\ngit clone https://github.com/LotusInputMethod/fcitx5-lotus.git\ncd fcitx5-lotus\ncmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=/usr/lib .\nmake\nsudo make install" - }, - "openSUSE": { - "Package Manager": "sudo rpm --import https://fcitx5-lotus.pages.dev/pubkey.gpg\nsudo zypper addrepo https://fcitx5-lotus.pages.dev/rpm/opensuse/fcitx5-lotus-tumbleweed.repo\nsudo zypper refresh\nsudo zypper install fcitx5-lotus", - "Binary": "sudo rpm -i fcitx5-lotus-*.rpm", - "Source": "sudo zypper install cmake extra-cmake-modules fcitx5-devel libinput-devel systemd-devel gcc-c++ go hicolor-icon-theme systemd-devel libX11-devel udev fcitx5-qt-devel\ngit clone https://github.com/LotusInputMethod/fcitx5-lotus.git\ncd fcitx5-lotus\ncmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=/usr/lib .\nmake\nsudo make install" - }, - "NixOS": { - "Package Manager": "inputs.fcitx5-lotus = {\n url = \"github:LotusInputMethod/fcitx5-lotus\";\n inputs.nixpkgs.follows = \"nixpkgs\";\n};\n\n# In configuration.nix:\nservices.fcitx5-lotus = {\n enable = true;\n user = \"your_username\";\n};", - "Binary": "NixOS prefers flake/module configuration.", - "Source": "NixOS prefers nix-shell or custom derivations." - } - }, - "server": { - "Other": { - "Bash": "sudo systemctl enable --now fcitx5-lotus-server@$(whoami).service || (sudo systemd-sysusers && sudo systemctl enable --now fcitx5-lotus-server@$(whoami).service)", - "Zsh": "sudo systemctl enable --now fcitx5-lotus-server@$(whoami).service || (sudo systemd-sysusers && sudo systemctl enable --now fcitx5-lotus-server@$(whoami).service)", - "Fish": "sudo systemctl enable --now fcitx5-lotus-server@(whoami).service; or begin; sudo systemd-sysusers; and sudo systemctl enable --now fcitx5-lotus-server@(whoami).service; end" - } - }, - "environment": { - "Bash": "cat <> ~/.bash_profile\nexport GTK_IM_MODULE=fcitx\nexport QT_IM_MODULE=fcitx\nexport XMODIFIERS=@im=fcitx\nexport SDL_IM_MODULE=fcitx\nexport GLFW_IM_MODULE=ibus\nEOF", - "Zsh": "cat <> ~/.zprofile\nexport GTK_IM_MODULE=fcitx\nexport QT_IM_MODULE=fcitx\nexport XMODIFIERS=@im=fcitx\nexport SDL_IM_MODULE=fcitx\nexport GLFW_IM_MODULE=ibus\nEOF", - "Fish": "echo 'if status is-login\n set -Ux GTK_IM_MODULE fcitx\n set -Ux QT_IM_MODULE fcitx\n set -Ux XMODIFIERS \"@im=fcitx\"\n set -gx SDL_IM_MODULE fcitx\n set -gx GLFW_IM_MODULE ibus\nend' >> ~/.config/fish/config.fish" - }, - "autostart": { - "GNOME": "GNOME Tweaks → Startup Applications → Add → Fcitx 5", - "KDE Plasma": "System Settings → Autostart → Add... → Add Application... → Fcitx 5", - "Xfce": "Settings → Session and Startup → Application Autostart → Add → Fcitx 5", - "Cinnamon": "System Settings → Startup Applications → + → Choose application → Fcitx 5", - "MATE": "Control Center → Startup Applications → Add (Name: Fcitx 5, Command: fcitx5)", - "Pantheon": "System Settings → Applications → Startup → Add Startup App... → Fcitx 5", - "Budgie": "Budgie Desktop Settings → Autostart → + → Add application → Fcitx 5", - "LXQt": "LXQt Configuration Center → Session Settings → Autostart → LXQt Autostart → Add (Name: Fcitx 5, Command: fcitx5)", - "COSMIC": "COSMIC Settings → Applications → Startup Applications → Add app → Fcitx 5", - "i3": "Add `exec --no-startup-id fcitx5 -d` to ~/.config/i3/config", - "Sway": "Add `exec --no-startup-id fcitx5 -d` to ~/.config/sway/config", - "Hyprland": "Add `exec-once = fcitx5 -d` to ~/.config/hypr/hyprland.conf" - }, - "wayland_extras": { - "General": { - "title": "Khuyến nghị Xwayland", - "description": "Ngay cả khi bạn chỉ dùng ứng dụng Wayland native, bật Xwayland vẫn được khuyến nghị. Nếu bảng gõ client-side không hoạt động, Fcitx sẽ chuyển sang cửa sổ X11 để đảm bảo vị trí hiển thị chính xác thay vì một cửa sổ Wayland ngẫu nhiên." - }, - "KDE Plasma": { - "best_setup": [ - "Sử dụng KDE Plasma 5.27 trở lên.", - "Biến môi trường: `XMODIFIERS=@im=fcitx` cho ứng dụng XWayland.", - "Vào **System Settings** -> **Virtual Keyboard** -> Chọn **Fcitx 5**.", - "Không đặt `GTK_IM_MODULE` & `QT_IM_MODULE` toàn cục.", - "Tham số trình duyệt: `--enable-features=UseOzonePlatform --ozone-platform=wayland --enable-wayland-ime`" - ], - "support_info": "Hỗ trợ text-input-v1/v2/v3 và zwp_input_method_v1.", - "caveats": "Một số ứng dụng Gtk/Qt cũ chỉ chạy X11 vẫn có thể cần đặt module riêng lẻ. Tránh đặt toàn cục để tránh lỗi nhấp nháy cửa sổ ứng viên." - }, - "GNOME": { - "best_setup": [ - "Biến môi trường: `XMODIFIERS=@im=fcitx` cho XWayland.", - "Qt5: `QT_IM_MODULE=fcitx`.", - "Qt >= 6.8.2: `QT_IM_MODULES=\"wayland;fcitx\"`.", - "Chrome: Chạy qua XWayland với `GTK_IM_MODULE=fcitx`." - ], - "support_info": "Sử dụng text-input-v3 và giao thức ibus dbus.", - "caveats": "Gnome-shell UI không hiển thị được popup ứng viên. Giải pháp duy nhất là sử dụng extension Kimpanel." - }, - "Sway": { - "best_setup": [ - "Yêu cầu Sway 1.10 trở lên.", - "Biến môi trường: `XMODIFIERS=@im=fcitx` (XWayland).", - "Qt5: `QT_IM_MODULE=fcitx`.", - "Qt >= 6.8.2: `QT_IM_MODULES=\"wayland;fcitx\"`." - ], - "support_info": "Hỗ trợ text-input-v3 và zwp_input_method_v2 (từ bản 1.10+).", - "caveats": "Qt < 6.8.2 cần `QT_IM_MODULE=fcitx` do Sway chưa hỗ trợ text-input-v2." - }, - "Weston": { - "best_setup": [ - "Đặt `GTK_IM_MODULE=fcitx` và `QT_IM_MODULE=fcitx`.", - "Cấu hình `~/.config/weston.ini`:", - "[core]\nxwayland=true\n\n[input-method]\npath=/usr/bin/fcitx5" - ], - "support_info": "Sử dụng text-input-v1 và zwp_input_method_v1.", - "caveats": "Do thiếu text-input-v3, IM module là giải pháp duy nhất cho Gtk/Qt." - } - } - } -}; +const selectedEnv = ref(environments[1]); const activateServerCode = computed(() => { if (selectedDistro.value === 'NixOS') return '# Bước này đã được cấu hình trong flake.nix ở trên.'; @@ -153,7 +41,16 @@ const serverCmd = computed(() => { }); const envCmd = computed(() => { - let vars = []; + // Default for X11 and other Wayland DEs + const defaultVars = [ + "export GTK_IM_MODULE=fcitx", + "export QT_IM_MODULE=fcitx", + "export XMODIFIERS=@im=fcitx", + "export SDL_IM_MODULE=fcitx", + "export GLFW_IM_MODULE=ibus" + ]; + + let vars; if (selectedEnv.value === 'Wayland') { if (selectedDe.value === 'KDE Plasma') { @@ -169,24 +66,10 @@ const envCmd = computed(() => { "export GLFW_IM_MODULE=ibus" ]; } else { - // Weston & others default - vars = [ - "export GTK_IM_MODULE=fcitx", - "export QT_IM_MODULE=fcitx", - "export XMODIFIERS=@im=fcitx", - "export SDL_IM_MODULE=fcitx", - "export GLFW_IM_MODULE=ibus" - ]; + vars = defaultVars; } } else { - // X11 - vars = [ - "export GTK_IM_MODULE=fcitx", - "export QT_IM_MODULE=fcitx", - "export XMODIFIERS=@im=fcitx", - "export SDL_IM_MODULE=fcitx", - "export GLFW_IM_MODULE=ibus" - ]; + vars = defaultVars; } if (selectedShell.value === 'Bash') { @@ -219,54 +102,26 @@ const copyToClipboard = async (text: string) => { }; const installStepCode = computed(() => { - return logic.steps.install[selectedDistro.value][selectedMethod.value]; + const distroInfo = logic.steps.install[selectedDistro.value as keyof typeof logic.steps.install]; + if (!distroInfo) return 'Cấu hình chưa sẵn sàng.'; + return (distroInfo as any)[selectedMethod.value] || 'Phương thức chưa sẵn sàng.'; }); -const autostartText = computed(() => logic.steps.autostart[selectedDe.value]); - -const waylandExtras = computed(() => { - if (selectedEnv.value !== 'Wayland') return []; - const compositor = selectedDe.value; - const extras: any[] = []; +const autostartText = computed(() => logic.steps.autostart[selectedDe.value as keyof typeof logic.steps.autostart]); - if (compositor === 'KDE Plasma') { - extras.push({ - title: "KDE Plasma (Virtual Keyboard)", - desc: "Kích hoạt giao thức text-input:", - instruction: "System Settings → Keyboard → Virtual Keyboard → Chọn Fcitx 5" - }); - } else if (compositor === 'Hyprland') { - extras.push({ - title: "Hyprland Support", - desc: "Thêm quyền hạn cho bộ gõ:", - code: "permission = fcitx5-lotus-server, keyboard, allow" - }); - } - - // Common for Chrome/Electron on Wayland - extras.push({ - title: "Chromium / Electron", - desc: "Bật hỗ trợ bộ gõ Wayland:", - code: "--enable-features=UseOzonePlatform --ozone-platform=wayland --enable-wayland-ime --wayland-text-input-version=3" - }); +// Wayland Logic +const waylandGeneral = computed(() => { + if (selectedEnv.value !== 'Wayland') return null; + return logic.steps.wayland_extras.General; +}); - return extras; +const waylandDeSpecific = computed(() => { + if (selectedEnv.value !== 'Wayland') return null; + return (logic.steps.wayland_extras as any)[selectedDe.value] || null; }); -const fcitx5Config = { - steps: [ - 'Mở Fcitx5 Configuration (tìm trong menu hoặc chạy fcitx5-configtool).', - 'Tìm Lotus ở cột bên phải.', - 'Nhấn mũi tên < để thêm nó sang cột bên trái.', - 'Bấm Apply để lưu thay đổi.' - ] -}; +const chromiumWaylandFlags = "--enable-features=UseOzonePlatform --ozone-platform=wayland --enable-wayland-ime --wayland-text-input-version=3"; -const kanataConfig = { - title: "Cấu hình Kanata", - desc: "Nếu dùng Kanata, hãy loại bỏ Uinput Server khỏi danh sách quét:", - code: "(defcfg\n ...\n linux-dev-names-exclude (\"Lotus-Uinput-Server\")\n ...\n)" -};