#Requires -Version 5.1 <# .SYNOPSIS Installs tmux (terminal multiplexer) and deploys .tmux.conf. .DESCRIPTION Installs tmux via winget (arndawg.tmux-windows) and deploys a customized .tmux.conf to the current user's home directory. Supported platforms: - Windows x64 (AMD64 / Intel 64bit) - Windows ARM64 Prerequisites: - winget (Windows Package Manager) — built into Windows 10 1709+ .EXAMPLE .\install-tmux.ps1 # One-liner install from remote: powershell -ExecutionPolicy Bypass -c "$t=\"$env:TEMP\install-tmux.ps1\"; iwr -useb 'https://gl.isitsoft.kr/publicproj/install-sh/-/raw/main/install-tmux.ps1' -OutFile $t; & $t" .NOTES If execution policy error occurs: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser #> [CmdletBinding()] param() Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' # ──────────────────────────────────────────── # Utility functions # ──────────────────────────────────────────── function Info { Write-Host "[INFO] $args" -ForegroundColor Cyan } function Warn { Write-Host "[WARN] $args" -ForegroundColor Yellow } function Success { Write-Host "[OK] $args" -ForegroundColor Green } function ErrExit { Write-Host "[ERROR] $args" -ForegroundColor Red; exit 1 } # ──────────────────────────────────────────── # Constants # ──────────────────────────────────────────── $ConfFile = Join-Path $env:USERPROFILE '.tmux.conf' # ──────────────────────────────────────────── # Step 1: Install tmux # ──────────────────────────────────────────── Info "Installing tmux..." $tmuxCmd = Get-Command tmux -ErrorAction SilentlyContinue if ($tmuxCmd) { $currentVer = & tmux -V 2>$null if (-not $currentVer) { $currentVer = "unknown" } Info "tmux is already installed ($currentVer). Skipping installation." } else { if (-not (Get-Command winget -ErrorAction SilentlyContinue)) { ErrExit "winget is required. Install it from the Microsoft Store or https://learn.microsoft.com/en-us/windows/package-manager/winget/" } winget install --id arndawg.tmux-windows --accept-package-agreements --accept-source-agreements 2>&1 | Out-Null Success "tmux installed via winget" } # ──────────────────────────────────────────── # Verify tmux is available and add to PATH permanently if needed # ──────────────────────────────────────────── $tmuxBin = $null # 1) Try current PATH $tmuxCmd = Get-Command tmux -ErrorAction SilentlyContinue if ($tmuxCmd) { $tmuxBin = $tmuxCmd.Source } # 2) Refresh PATH from registry (winget may have added paths) if (-not $tmuxBin) { $env:Path = [System.Environment]::GetEnvironmentVariable('Path', 'User') + ';' + [System.Environment]::GetEnvironmentVariable('Path', 'Machine') $tmuxCmd = Get-Command tmux -ErrorAction SilentlyContinue if ($tmuxCmd) { $tmuxBin = $tmuxCmd.Source } } # 3) Search common locations where winget installs tmux-windows if (-not $tmuxBin) { $searchDirs = @( (Join-Path $env:LOCALAPPDATA 'Microsoft\WinGet\Links'), (Join-Path $env:LOCALAPPDATA 'Programs\tmux-windows'), 'C:\Program Files\tmux-windows', 'C:\Program Files (x86)\tmux-windows' ) foreach ($dir in $searchDirs) { if (Test-Path $dir) { $candidate = Join-Path $dir 'tmux.exe' if (Test-Path $candidate) { $tmuxBin = $candidate; break } } } # Recurse under WinGet/Packages for tmux if (-not $tmuxBin -and (Test-Path (Join-Path $env:LOCALAPPDATA 'Microsoft\WinGet\Packages'))) { $found = Get-ChildItem -Path (Join-Path $env:LOCALAPPDATA 'Microsoft\WinGet\Packages') -Recurse -Filter 'tmux.exe' -ErrorAction SilentlyContinue | Select-Object -First 1 if ($found) { $tmuxBin = $found.FullName } } } if ($tmuxBin) { # Add tmux's directory to PATH for this session $tmuxDir = Split-Path $tmuxBin if ($env:Path -notlike "*$tmuxDir*") { $env:Path = "$tmuxDir;$env:Path" Info "Added $tmuxDir to PATH for this session" } Success "tmux is available: $tmuxBin" # Permanently add tmux's directory to user PATH if not already there $userPath = [System.Environment]::GetEnvironmentVariable('Path', 'User') if ($userPath -notlike "*$tmuxDir*") { [System.Environment]::SetEnvironmentVariable('Path', "$tmuxDir;$userPath", 'User') Success "Added $tmuxDir to user PATH permanently (takes effect on next login)" } else { Info "$tmuxDir already in user PATH" } } else { Warn "tmux was not found in PATH after installation." Warn "Please restart your terminal or add tmux's directory to your PATH manually." } # ──────────────────────────────────────────── # Step 2: Deploy .tmux.conf # ──────────────────────────────────────────── if (Test-Path $ConfFile) { $timestamp = Get-Date -Format 'yyyyMMddHHmmss' $backup = "${ConfFile}.bak.${timestamp}" Copy-Item $ConfFile $backup Warn "Existing .tmux.conf found at $ConfFile" Info "Backup saved to $backup" } $tmuxConf = @' # .tmux.conf - tmux-windows compatible # # Based on: https://github.com/arndawg/tmux-windows/blob/master/example_tmux.conf # Prefix key (default is Ctrl-b, changed to Ctrl-a) set -g prefix C-a unbind C-b bind C-a send-prefix # Terminal settings (important for Windows compatibility) set -g default-terminal "tmux-256color" set-option -sa terminal-features ",xterm*:RGB" # No bells set -g bell-action none # Split panes with current path bind | split-window -h -c "#{pane_current_path}" bind - split-window -v -c "#{pane_current_path}" unbind '"' unbind % # Pane navigation (vim-style) bind h select-pane -L bind j select-pane -D bind k select-pane -U bind l select-pane -R # Window navigation bind -r C-h previous-window bind -r C-l next-window # Layout bind Space next-layout bind o rotate-window # Window management bind , command-prompt "rename-window %%" bind & kill-window # Reload config bind r source-file ~/.tmux.conf \; display "Reloaded!" # Status bar set -g status-bg colour235 set -g status-fg colour136 set -g status-left-length 40 set -g status-right-length 40 set -g status-interval 5 set -g history-limit 10000 set -g status-left '#[fg=green]#S #[fg=yellow]#H' set -g status-right '#[fg=cyan]%Y-%m-%d #[fg=green]%H:%M:%S' # Pane border colors set-option -g pane-border-style 'fg=colour244' set-option -g pane-active-border-style 'fg=colour77' # Copy mode with vi keys setw -g mode-keys vi # Mouse support (without copy mode dragging) set -g mouse on unbind -n MouseDrag1Pane unbind -Tcopy-mode MouseDrag1Pane # for pi set -g extended-keys on set -g extended-keys-format csi-u '@ [System.IO.File]::WriteAllText($ConfFile, $tmuxConf, [System.Text.UTF8Encoding]::new($false)) Success ".tmux.conf deployed to $ConfFile" # ──────────────────────────────────────────── # Step 3: Post-install notes # ──────────────────────────────────────────── Info "" Info "==================================================" Success "tmux installation complete!" Info "==================================================" if ($tmuxBin) { Info "" Info "tmux binary: $tmuxBin" } Info "" Info "IMPORTANT: Close this terminal and open a new one to use tmux." Info "PATH changes require a new terminal session to take effect." Info "" Info "RECOMMENDED: On Windows 10, use Windows Terminal instead of CMD.exe." Info "Install it from: winget install Microsoft.WindowsTerminal" Info "Windows Terminal supports true color, Unicode, and tmux panes properly." Info "" Info "Getting started:" Info " tmux - Start a new session" Info " tmux new -s - Start a named session" Info " tmux attach -t - Attach to a session" Info " tmux ls - List sessions" Info "" Info "Key bindings (customized via .tmux.conf):" Info " Ctrl-a | - Split horizontally" Info " Ctrl-a - - Split vertically" Info " Ctrl-a h/j/k/l - Navigate panes (vim-style)" Info " Ctrl-a r - Reload .tmux.conf" Info "" Info "Config file: $ConfFile"