From c0058e6719c71edf408877af1a6519887c261dbd Mon Sep 17 00:00:00 2001 From: Jerry Chae Date: Tue, 2 Jun 2026 11:20:59 +0900 Subject: [PATCH] =?UTF-8?q?helix=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 49 ++++++++++- install-helix.ps1 | 213 ++++++++++++++++++++++++++++++++++++++++++++++ install-helix.sh | 179 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 439 insertions(+), 2 deletions(-) create mode 100644 install-helix.ps1 create mode 100644 install-helix.sh diff --git a/README.md b/README.md index 53e221e..e724fd2 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ ### πŸ“ 1. 터미널 관리 & 파일 μœ ν‹Έλ¦¬ν‹° * **[tmux](https://github.com/tmux/tmux)** - κ°•λ ₯ν•œ 터미널 λ©€ν‹°ν”Œλ ‰μ„œ (μ„Έμ…˜ 관리 및 ν™”λ©΄ λΆ„ν• , WindowsλŠ” psmux둜 μ„€μΉ˜) +* **[Helix](https://github.com/helix-editor/helix)** - ν˜„λŒ€μ μ΄κ³  κ°•λ ₯ν•œ 터미널 기반 λͺ¨λ‹¬ ν…μŠ€νŠΈ 에디터 (LSP 및 ꡬ문 κ°•μ‘° κΈ°λ³Έ λ‚΄μž₯) * **[superfile](https://github.com/yorukot/superfile)** - λͺ¨λ˜ν•˜κ³  μˆ˜λ €ν•œ 터미널 기반 파일 κ΄€λ¦¬μž (Vim 킀바인딩 지원) * **[dua](https://github.com/byron/dua-cli)** - 병렬 μŠ€μΊ”μ„ μ§€μ›ν•˜λŠ” μ΄ˆκ³ μ† λ””μŠ€ν¬ μ‚¬μš©λŸ‰ 뢄석 도ꡬ @@ -38,6 +39,11 @@ curl -fsSL "https://gl.isitsoft.kr/publicproj/install-sh/-/raw/main/install-tmux.sh?ref_type=heads" | bash ``` +* **Helix:** + ```bash + curl -fsSL "https://gl.isitsoft.kr/publicproj/install-sh/-/raw/main/install-helix.sh?ref_type=heads" | bash + ``` + * **superfile:** ```bash curl -fsSL "https://gl.isitsoft.kr/publicproj/install-sh/-/raw/main/install-superfile.sh?ref_type=heads" | bash @@ -117,6 +123,16 @@ > πŸ’‘ **Windows OpenSSH Server μ°Έκ³ :** 슀크립트 가동 μ‹œ OpenSSH Server(sshd)κ°€ λ―Έμ„€μΉ˜λœ μƒνƒœλΌλ©΄ μžλ™μœΌλ‘œ 감지 및 λ°±κ·ΈλΌμš΄λ“œ μ„€μΉ˜ ν›„ κΈ°λ™ν•©λ‹ˆλ‹€. (κ΄€λ¦¬μž κΆŒν•œμ΄ ν•„μš”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.) > πŸ’‘ **Windows tmux(psmux) μ°Έκ³ :** Windows ν™˜κ²½μ—μ„œλŠ” Rust 기반으둜 λΉŒλ“œλ˜μ–΄ μ„±λŠ₯이 λ›°μ–΄λ‚œ λ„€μ΄ν‹°λΈŒ Windows 터미널 λ©€ν‹°ν”Œλ ‰μ„œμΈ `psmux`κ°€ μ„€μΉ˜λ©λ‹ˆλ‹€. +* **Helix:** + * **CMD μ°½μ—μ„œ μ„€μΉ˜ μ‹œ:** + ```cmd + powershell -ExecutionPolicy Bypass -c "[Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; $t=\"$env:TEMP\install-helix.ps1\"; iwr -useb 'https://gl.isitsoft.kr/publicproj/install-sh/-/raw/main/install-helix.ps1' -OutFile $t; & $t" + ``` + * **νŒŒμ›Œμ‰˜ μ°½μ—μ„œ μ„€μΉ˜ μ‹œ:** + ```powershell + $t="$env:TEMP\install-helix.ps1"; iwr -useb 'https://gl.isitsoft.kr/publicproj/install-sh/-/raw/main/install-helix.ps1' -OutFile $t; powershell -ExecutionPolicy Bypass -File $t + ``` + * **superfile:** * **CMD μ°½μ—μ„œ μ„€μΉ˜ μ‹œ:** ```cmd @@ -258,7 +274,36 @@ tmux ls # 가동 쀑인 μ„Έμ…˜ λͺ©λ‘ 보기 > πŸ’‘ **Windows (PowerShell) μ°Έκ³ :** μœˆλ„μš° ν™˜κ²½μ—μ„œ μ‹€ν–‰ν•  경우, OpenSSH Server μ„œλΉ„μŠ€(`sshd`)κ°€ μž‘λ™ν•˜μ§€ μ•Šκ±°λ‚˜ 없을 μ‹œ Windows 선택적 κΈ°λŠ₯(Optional Capability)을 ν†΅ν•˜μ—¬ 무인 μ„€μΉ˜ 및 κ΅¬λ™κΉŒμ§€ μ™„μ „ μžλ™ μ§€μ›ν•©λ‹ˆλ‹€. > πŸ’‘ **Windows psmux 연동 μ°Έκ³ :** Windowsμ—μ„œλŠ” λ„€μ΄ν‹°λΈŒ 가상 터미널 ν™˜κ²½μ„ μ„ μ‚¬ν•˜λŠ” `psmux`κ°€ μ„€μΉ˜λ˜λ©°, κΈ°μ‘΄ `.tmux.conf` 파일과 높은 μˆ˜μ€€μœΌλ‘œ ν˜Έν™˜λ˜μ–΄ λ™μΌν•œ μ„€μ •κ³Ό vim 킀바인딩을 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. -#### 1.2. superfile +#### 1.2. Helix +터미널 ν™˜κ²½μ—μ„œ ν˜„λŒ€μ μΈ μ‚¬μš©μ„±μ„ μ œκ³΅ν•˜λŠ” λͺ¨λ‹¬(Modal) ν…μŠ€νŠΈ μ—λ””ν„°μž…λ‹ˆλ‹€. λ³„λ„μ˜ ν”ŒλŸ¬κ·ΈμΈ μ„€μ • 없이도 LSP(Language Server Protocol), λ‚˜λ¬΄ λͺ¨μ–‘ ꡬ문 트리 νŒŒμ„œ(Tree-sitter) 및 μˆ˜λ €ν•œ λ””μžμΈ ν…Œλ§ˆκ°€ λ‚΄μž₯λ˜μ–΄ μžˆμ–΄ μ΄ˆλ³΄μžλΆ€ν„° μ „λ¬Έκ°€κΉŒμ§€ μ¦‰μ‹œ μ‚¬μš© κ°€λŠ₯ν•©λ‹ˆλ‹€. + +* **LSP κΈ°λ³Έ λ‚΄μž₯** β€” μžλ™ μ™„μ„±, μ •μ˜ 이동, νƒ€μž… 힌트 λ“± IDEκΈ‰ 개발 지원 +* **Tree-sitter ꡬ문 뢄석** β€” μ‹€μ‹œκ°„ ꡬ문 뢄석을 ν†΅ν•œ μ™„λ²½ν•œ 색상 ν•˜μ΄λΌμ΄νŒ… 및 슀마트 μ˜μ—­ 탐색 +* **λͺ¨λ‹¬ νŽΈμ§‘ λͺ¨λ“œ** β€” Vimκ³Ό μœ μ‚¬ν•˜λ©΄μ„œλ„ 더 ν˜„λŒ€μ μΈ 닀쀑 μ»€μ„œ 및 ν…μŠ€νŠΈ 객체 νŽΈμ§‘ 지원 + +```bash +hx # μ‹€ν–‰ λͺ…λ Ήμ–΄ +``` + +| 단좕킀 | λ™μž‘ | +| :--- | :--- | +| `i` | Insert λͺ¨λ“œ μ§„μž… | +| `Esc` | Normal λͺ¨λ“œ 볡귀 | +| `d` | ν˜„μž¬ 선택 μ˜μ—­ μ‚­μ œ (μ§€μš°κΈ°) | +| `y` | ν˜„μž¬ 선택 μ˜μ—­ 볡사 (Yank) | +| `p` | λ³΅μ‚¬ν•œ ν…μŠ€νŠΈ λΆ™μ—¬λ„£κΈ° (Paste) | +| `w` | λ‹€μŒ λ‹¨μ–΄λ‘œ 이동 | +| `b` | 이전 λ‹¨μ–΄λ‘œ 이동 | +| `u` | μž‘μ—… μ·¨μ†Œ (Undo) | +| `U` | μ·¨μ†Œ μ·¨μ†Œ (Redo) | +| `Space f` | μ „μ—­ 파일 μ°ΎκΈ° (File picker) | +| `Space /` | ν˜„μž¬ 버퍼 μ „μ—­ 검색 | +| `:w` | 파일 μ €μž₯ | +| `:q` | 에디터 μ’…λ£Œ | + +> πŸ’‘ **μ„€μΉ˜ ꡬ성 팁:** Helix μ—λ””ν„°λŠ” μ‹€ν–‰ λ°”μ΄λ„ˆλ¦¬(`hx` / `hx.exe`)뿐만 μ•„λ‹ˆλΌ 언어별 ꡬ문 및 ν…Œλ§ˆ 파일이 λͺ¨μΈ `runtime` 디렉토리가 μ˜¬λ°”λ₯Έ κ²½λ‘œμ— λ°°ν¬λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€. 당사 배포 μŠ€ν¬λ¦½νŠΈλŠ” macOS/Linux의 경우 `~/.config/helix/runtime`, Windows의 경우 `%APPDATA%\helix\runtime`으둜 λŸ°νƒ€μž„ 폴더λ₯Ό μžλ™ νƒμƒ‰ν•˜μ—¬ λ°±μ—… 및 λ°°μΉ˜ν•©λ‹ˆλ‹€. + +#### 1.3. superfile μˆ˜λ €ν•˜κ³  λ―Έλ €ν•œ λ””μžμΈμ„ μ„ μ‚¬ν•˜λŠ” κ³ κΈ°λŠ₯ 터미널 파일 κ΄€λ¦¬μžμž…λ‹ˆλ‹€. * **λ“€μ–Ό νŒ¨λ„** β€” λŒ€μΉ­ν˜• λ ˆμ΄μ•„μ›ƒμœΌλ‘œ 직관적인 디렉토리 κ°„ 파일 μ‘°μž‘ @@ -283,7 +328,7 @@ spf # μ‹€ν–‰ λͺ…λ Ήμ–΄ (superfile이 μ•„λ‹Œ spfλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€) > πŸ’‘ **μ€‘μš”:** 터미널 μ•„μ΄μ½˜μ΄ λ°•μŠ€λ‚˜ λ¬ΌμŒν‘œ 기호처럼 κΉ¨μ Έ 보일 경우, μ‚¬μš©ν•˜μ‹œλŠ” 터미널 폰트λ₯Ό **Nerd Font** κ³„μ—΄λ‘œ μ„€μ •ν•΄ μ£Όμ„Έμš”. > πŸ’‘ **macOS iTerm2 ν•œκΈ€ 깨짐 팁:** μ„€μ •(`Settings` > `Profile` > `Text` > `Normalization`)μ—μ„œ **NFC** μ˜΅μ…˜μœΌλ‘œ 섀정을 μ „ν™˜ν•˜μ‹œλ©΄ 정상 ν‘œκΈ°λ©λ‹ˆλ‹€. -#### 1.3. dua +#### 1.4. dua SSD와 μ‹œμŠ€ν…œ μ„±λŠ₯을 μ΅œλŒ€λ‘œ ν™œμš©ν•˜μ—¬ μœ μ‹€λœ μš©λŸ‰μ„ μΆ”μ ν•˜λŠ” 병렬 μŠ€μΊ” λ°©μ‹μ˜ μ΄ˆκ³ μ† λ””μŠ€ν¬ 뢄석 μœ ν‹Έλ¦¬ν‹°μž…λ‹ˆλ‹€. * **μ΄ˆκ³ μ† μŠ€μΊ”** β€” λŒ€μš©λŸ‰ λ””μŠ€ν¬λ„ 수 초 λ§Œμ— κ³ μ†μœΌλ‘œ μŠ€μΊ” 처리 diff --git a/install-helix.ps1 b/install-helix.ps1 new file mode 100644 index 0000000..e31d8ab --- /dev/null +++ b/install-helix.ps1 @@ -0,0 +1,213 @@ +#Requires -Version 5.1 +<# +.SYNOPSIS + Installs Helix Editor (TUI text editor) and its runtime directory on Windows. + +.DESCRIPTION + Auto-detects the latest release from https://github.com/helix-editor/helix/releases, + downloads the x86_64-windows.zip archive, extracts it, installs hx.exe + to your local bin directory, and deploys the essential runtime files + to %APPDATA%\helix\runtime. + + Supported architectures: + - Windows x64 (AMD64 / Intel 64bit) + +.PARAMETER InstallDir + Directory to install hx.exe. Default: $env:USERPROFILE\.local\bin + +.PARAMETER AddToPath + Whether to permanently add InstallDir to user PATH. Default: $true + +.EXAMPLE + .\install-helix.ps1 + + # One-liner install from remote (works on Windows 10+): + powershell -ExecutionPolicy Bypass -c "[Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; $t=\"$env:TEMP\install-helix.ps1\"; iwr -useb 'https://gl.isitsoft.kr/publicproj/install-sh/-/raw/main/install-helix.ps1' -OutFile $t; & $t" + +.NOTES + If execution policy error occurs: + Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser +#> + +[CmdletBinding()] +param( + [string] $InstallDir = "$env:USERPROFILE\.local\bin", + [bool] $AddToPath = $true +) + +# μ΅œμ‹  μœˆλ„μš° ν™˜κ²½ 및 μ—λŸ¬ λ°œμƒ μ‹œ μ¦‰μ‹œ 쀑단 μ„€μ • +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +# HTTPS λ‹€μš΄λ‘œλ“œλ₯Ό μœ„ν•œ TLS 1.2 κ°•μ œ (Windows 7/10 및 PowerShell 5.1 ν˜Έν™˜μ„± 보μž₯) +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + +# ──────────────────────────────────────────── +# μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜ μ •μ˜ (λͺ¨λ“  μ•ˆλ‚΄ λ¬Έκ΅¬λŠ” 영문으둜 μž‘μ„±) +# ──────────────────────────────────────────── +function Write-Info { param([string]$msg) Write-Host "[INFO] $msg" -ForegroundColor Cyan } + # 정보 좜λ ₯ +function Write-Warn { param([string]$msg) Write-Host "[WARN] $msg" -ForegroundColor Yellow } + # κ²½κ³  좜λ ₯ +function Write-Success { param([string]$msg) Write-Host "[OK] $msg" -ForegroundColor Green } + # 성곡 좜λ ₯ +function Write-Err { param([string]$msg) Write-Host "[ERROR] $msg" -ForegroundColor Red; exit 1 } + # μ—λŸ¬ 좜λ ₯ 및 슀크립트 κ°•μ œ μ’…λ£Œ + +# ──────────────────────────────────────────── +# μƒμˆ˜ μ •μ˜ +# ──────────────────────────────────────────── +$REPO = "helix-editor/helix" +$API_URL = "https://api.github.com/repos/$REPO/releases/latest" +$HELIX_CONFIG_DIR = Join-Path $env:APPDATA "helix" + +# ──────────────────────────────────────────── +# 메인 μ„€μΉ˜ ν”„λ‘œμ„ΈμŠ€ +# ──────────────────────────────────────────── +function Main { + Write-Info "===== Helix Editor install script (Windows PowerShell) =====" + + # 1) 운영체제 μ•„ν‚€ν…μ²˜ 감지 (HelixλŠ” ν˜„μž¬ 64λΉ„νŠΈ Windows λΉŒλ“œλ§Œ 곡식 배포) + $envArch = $env:PROCESSOR_ARCHITEW6432 + if (-not $envArch) { $envArch = $env:PROCESSOR_ARCHITECTURE } + if ($envArch -ne "AMD64" -and $envArch -ne "ARM64") { + Write-Err "Helix editor only provides 64-bit Windows builds. Detected architecture: $envArch" + } + + # 2) GitHub μ΅œμ‹  릴리슀 정보 νšλ“ + Write-Info "Fetching latest Helix release information from GitHub API..." + try { + $release = Invoke-RestMethod -Uri $API_URL -UseBasicParsing -Headers @{ 'User-Agent' = 'install-helix-ps1' } + } catch { + Write-Err "GitHub API call failed: $_" + } + + $tagName = $release.tag_name + $version = $tagName -replace '^v', '' + Write-Info "Latest Helix version confirmed: $tagName" + + # 3) μœˆλ„μš° x86_64용 zip 파일 에셋 탐색 + $asset = $release.assets | Where-Object { $_.name -like "*-x86_64-windows.zip" } | Select-Object -First 1 + if (-not $asset) { + # 에셋 μ‘°νšŒκ°€ λ˜μ§€ μ•Šμ„ 경우 릴리슀 νŒ¨ν„΄μ— λ§žμΆ”μ–΄ λ‹€μš΄λ‘œλ“œ URL 직접 λΉŒλ“œ + $zipName = "helix-${version}-x86_64-windows.zip" + $downloadUrl = "https://github.com/$REPO/releases/download/$tagName/$zipName" + Write-Warn "Could not find asset in GitHub response. Trying fallback URL: $downloadUrl" + } else { + $zipName = $asset.name + $downloadUrl = $asset.browser_download_url + } + + # 4) μž„μ‹œ μž‘μ—… 디렉토리 생성 및 μ•„μΉ΄μ΄λΈŒ λ‹€μš΄λ‘œλ“œ + $tmpDir = Join-Path $env:TEMP "helix_install_$(Get-Random)" + New-Item -ItemType Directory -Path $tmpDir -Force | Out-Null + $tmpZipPath = Join-Path $tmpDir $zipName + + try { + Write-Info "Downloading archive: $downloadUrl" + $ProgressPreference = 'SilentlyContinue' # λ‹€μš΄λ‘œλ“œ 속도 ν–₯상을 μœ„ν•΄ μ§„ν–‰λ°” μˆ¨κΉ€ + Invoke-WebRequest -Uri $downloadUrl -OutFile $tmpZipPath -UseBasicParsing + $ProgressPreference = 'Continue' + + # 5) μ••μΆ• ν•΄μ œ + Write-Info "Extracting archive..." + Expand-Archive -Path $tmpZipPath -DestinationPath $tmpDir -Force + + # μ••μΆ• ν•΄μ œ 폴더 탐색 (helix-vXX.XX.X-x86_64-windows ꡬ쑰) + $extractedFolder = Get-ChildItem -Path $tmpDir -Directory | Where-Object { $_.Name -like "helix-*" } | Select-Object -First 1 + if (-not $extractedFolder) { + Write-Err "Failed to find extracted Helix directory in temporary path." + } + + # 6) λ°”μ΄λ„ˆλ¦¬ 볡사 (hx.exe) + $hxExe = Join-Path $extractedFolder.FullName "hx.exe" + if (-not (Test-Path $hxExe)) { + Write-Err "hx.exe not found in the extracted folder: $($extractedFolder.FullName)" + } + + if (-not (Test-Path $InstallDir)) { + Write-Info "Creating installation directory: $InstallDir" + New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null + } + + $destExePath = Join-Path $InstallDir "hx.exe" + Write-Info "Deploying binary to: $destExePath" + Copy-Item -Path $hxExe -Destination $destExePath -Force + + # 7) λŸ°νƒ€μž„(runtime) 디렉토리 μ„€μΉ˜ + # Helix μ—λ””ν„°λŠ” ν…Œλ§ˆ, μ–Έμ–΄ 쿼리 등을 λ‘œλ“œν•˜κΈ° μœ„ν•΄ runtime 디렉토리가 ν•„μˆ˜μ μœΌλ‘œ μš”κ΅¬λ©λ‹ˆλ‹€. + # Windows의 경우 %APPDATA%\helix\runtime에 λŸ°νƒ€μž„ 폴더가 λ³΅μ‚¬λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€. + $srcRuntime = Join-Path $extractedFolder.FullName "runtime" + if (-not (Test-Path $srcRuntime)) { + Write-Err "Runtime directory not found in the extracted folder." + } + + $destRuntime = Join-Path $HELIX_CONFIG_DIR "runtime" + if (Test-Path $destRuntime) { + Write-Warn "Existing Helix runtime directory detected: $destRuntime" + $backupRuntime = "${destRuntime}.bak.$(Get-Date -Format 'yyyyMMddHHmmss')" + Write-Info "Backing up existing runtime to: $backupRuntime" + # λ™μΌν•œ λ“œλΌμ΄λΈŒ λ‚΄ Rename을 μˆ˜ν–‰ν•˜κΈ° μœ„ν•΄ μƒˆ 폴더λͺ…(μ΄λ¦„λ§Œ)을 μ œκ³΅ν•©λ‹ˆλ‹€. + Rename-Item -Path $destRuntime -NewName (Split-Path $backupRuntime -Leaf) -Force + } + + if (-not (Test-Path $HELIX_CONFIG_DIR)) { + New-Item -ItemType Directory -Path $HELIX_CONFIG_DIR -Force | Out-Null + } + + Write-Info "Deploying runtime directory to: $destRuntime" + Copy-Item -Path $srcRuntime -Destination $destRuntime -Recurse -Force + + } finally { + # μž„μ‹œ λ‹€μš΄λ‘œλ“œ 파일 및 μ••μΆ• ν•΄μ œ 디렉토리 정리 + if (Test-Path $tmpDir) { + Remove-Item -Path $tmpDir -Recurse -Force -ErrorAction SilentlyContinue | Out-Null + } + } + + # 8) PATH ν™˜κ²½ λ³€μˆ˜ 영ꡬ 등둝 + if ($AddToPath) { + # ν˜„μž¬ μ„Έμ…˜ PATH 반영 + if ($env:Path -notlike "*$InstallDir*") { + $env:Path = "$InstallDir;$env:Path" + Write-Info "Temporarily added $InstallDir to current session PATH." + } + + # μ‚¬μš©μž ν™˜κ²½ λ³€μˆ˜ PATH 반영 + $userPath = [System.Environment]::GetEnvironmentVariable('Path', 'User') + if ($userPath -notlike "*$InstallDir*") { + [System.Environment]::SetEnvironmentVariable('Path', "$InstallDir;$userPath", 'User') + Write-Success "Permanently added $InstallDir to User PATH." + Write-Warn "Please restart your terminal window to apply the updated PATH environment variable." + } else { + Write-Info "$InstallDir is already registered in User PATH." + } + } + + # 9) μ΅œμ’… μ„€μΉ˜ μ™„λ£Œ 확인 및 검증 + if (Test-Path $destExePath) { + Write-Host "" + Write-Host "==================================================" -ForegroundColor Green + Write-Success "Helix Editor ($tagName) installation completed successfully!" + Write-Host "==================================================" -ForegroundColor Green + Write-Info "Run command: hx" + Write-Info "Config directory: $HELIX_CONFIG_DIR" + Write-Info "Runtime directory: $destRuntime" + Write-Host "" + Write-Info "Quick Vim-like shortcuts inside Helix:" + Write-Info " :q - Quit" + Write-Info " :w - Save" + Write-Info " i - Enter Insert mode" + Write-Info " Esc - Back to Normal mode" + Write-Info " hx --health - Check Helix system health" + } else { + Write-Err "Installation failed. hx.exe could not be verified at: $destExePath" + } +} + +# 예기치 λͺ»ν•œ 전체 ν”„λ‘œμ„ΈμŠ€ μ—λŸ¬ 감지λ₯Ό μœ„ν•œ Trap μ„€μ • +trap { + Write-Err "An unexpected error occurred during installation: $_" +} + +Main diff --git a/install-helix.sh b/install-helix.sh new file mode 100644 index 0000000..45722fc --- /dev/null +++ b/install-helix.sh @@ -0,0 +1,179 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2086 + +# GitHub Releasesμ—μ„œ μ΅œμ‹  Helix 에디터 TUIλ₯Ό λ‹€μš΄λ‘œλ“œν•˜κ³  ν•„μˆ˜ λŸ°νƒ€μž„μ„ μ„€μΉ˜ν•©λ‹ˆλ‹€. +# Helix: https://github.com/helix-editor/helix +# +# 지원 ν”Œλž«νΌ: +# macOS : Apple Silicon (arm64), Intel (x86_64) +# Linux : x86_64, aarch64(arm64) + +set -euo pipefail + +# ──────────────────────────────────────────── +# μƒμˆ˜ μ •μ˜ +# ──────────────────────────────────────────── +REPO="helix-editor/helix" +API_URL="https://api.github.com/repos/${REPO}/releases/latest" +INSTALL_DIR="${HOME}/.local/bin" +HELIX_CONFIG_DIR="${HOME}/.config/helix" + +# ──────────────────────────────────────────── +# μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜ (λͺ¨λ‘ stderr 좜λ ₯) +# ──────────────────────────────────────────── +info() { echo "[INFO] $*" >&2; } +warn() { echo "[WARN] $*" >&2; } +error() { echo "[ERROR] $*" >&2; exit 1; } +success() { echo "[OK] $*" >&2; } + +# ──────────────────────────────────────────── +# ν•„μˆ˜ λͺ…λ Ήμ–΄ 확인 +# ──────────────────────────────────────────── +for cmd in curl tar xz uname; do + command -v "$cmd" &>/dev/null || error "'$cmd' λͺ…λ Ήμ–΄κ°€ ν•„μš”ν•©λ‹ˆλ‹€. λ¨Όμ € μ„€μΉ˜ν•΄ μ£Όμ„Έμš”." +done + +# Fallback: jqκ°€ 없을 경우 python3λ₯Ό μ‚¬μš©ν•΄ JSON 뢄석 +if command -v jq &>/dev/null; then + _json_latest_tag() { + jq -r '.tag_name' + } +else + command -v python3 &>/dev/null || error "'jq' λ˜λŠ” 'python3' λͺ…λ Ήμ–΄κ°€ μ„€μΉ˜λ˜μ–΄ μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€." + _json_latest_tag() { + python3 -c " +import sys, json +data = json.load(sys.stdin) +print(data.get('tag_name', '')) +" + } +fi + +# ──────────────────────────────────────────── +# OS 및 μ•„ν‚€ν…μ²˜ 뢄석 +# ──────────────────────────────────────────── +# λ°˜ν™˜ ν˜•μ‹: "μ•„μΉ΄μ΄λΈŒμ•„ν‚€ν…μ²˜λͺ…" +detect_platform() { + local os arch + + os="$(uname -s)" + arch="$(uname -m)" + + case "$os" in + # ── macOS ────────────────────────────────────────────── + Darwin) + case "$arch" in + arm64) echo "aarch64-macos" ;; + x86_64) echo "x86_64-macos" ;; + *) error "μ§€μ›ν•˜μ§€ μ•ŠλŠ” macOS μ•„ν‚€ν…μ²˜μž…λ‹ˆλ‹€: $arch" ;; + esac + ;; + + # ── Linux ────────────────────────────────────────────── + Linux) + case "$arch" in + x86_64|amd64) + echo "x86_64-linux" ;; + aarch64|arm64) + echo "aarch64-linux" ;; + *) + error "μ§€μ›ν•˜μ§€ μ•ŠλŠ” Linux μ•„ν‚€ν…μ²˜μž…λ‹ˆλ‹€: $arch" ;; + esac + ;; + + *) + error "μ§€μ›ν•˜μ§€ μ•ŠλŠ” μš΄μ˜μ²΄μ œμž…λ‹ˆλ‹€: $os (uname -a: $(uname -a))" + ;; + esac +} + +# ──────────────────────────────────────────── +# μ΅œμ‹  릴리슀 νƒœκ·Έ κ°€μ Έμ˜€κΈ° +# ──────────────────────────────────────────── +get_latest_release_tag() { + info "GitHub APIλ₯Ό 톡해 Helix μ΅œμ‹  릴리슀 버전을 μ‘°νšŒν•˜λŠ” 쀑..." + + local release_json tag + release_json="$(curl -fsSL "${API_URL}")" || error "GitHub API ν˜ΈμΆœμ— μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€." + + tag="$(echo "$release_json" | _json_latest_tag)" + if [[ -z "$tag" || "$tag" == "null" ]]; then + error "μ΅œμ‹  릴리슀 νƒœκ·Έλ₯Ό ν™•μΈν•˜λŠ” 데 μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€." + fi + echo "$tag" +} + +# ──────────────────────────────────────────── +# 메인 μ„€μΉ˜ 둜직 +# ──────────────────────────────────────────── +main() { + local platform_arch + platform_arch="$(detect_platform)" + + local tag version + tag="$(get_latest_release_tag)" + version="${tag#v}" # v25.07.1 ν˜•νƒœμ—μ„œ v 접두사 제거 + + info "μ„€μΉ˜ ν™˜κ²½ 감지: $platform_arch ($tag 버전)" + + local asset_name="helix-${version}-${platform_arch}" + local archive_name="${asset_name}.tar.xz" + local download_url="https://github.com/helix-editor/helix/releases/download/${tag}/${archive_name}" + + # μž„μ‹œ μž‘μ—… 디렉토리 생성 + local tmp_dir + tmp_dir="$(mktemp -d)" + local tmp_archive="${tmp_dir}/${archive_name}" + + info "μ•„μΉ΄μ΄λΈŒ λ‹€μš΄λ‘œλ“œ 쀑: $download_url" + if ! curl -fsSL "$download_url" -o "$tmp_archive"; then + rm -rf "$tmp_dir" + error "λ°”μ΄λ„ˆλ¦¬ λ‹€μš΄λ‘œλ“œμ— μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€. URL: $download_url" + fi + + info "μ••μΆ• ν•΄μ œ 쀑..." + tar -xf "$tmp_archive" -C "$tmp_dir" + + local extracted_folder="${tmp_dir}/${asset_name}" + if [ -d "${extracted_folder}-source" ]; then + # κ°„ν˜Ή 폴더 이름 뒀에 -sourceκ°€ λΆ™λŠ” μ˜ˆμ™Έ λ°©μ–΄ + extracted_folder="${extracted_folder}-source" + fi + + # 1) λ°”μ΄λ„ˆλ¦¬ μ„€μΉ˜ + mkdir -p "$INSTALL_DIR" + local dest_binary="${INSTALL_DIR}/hx" + info "λ°”μ΄λ„ˆλ¦¬ 배포 쀑: $dest_binary" + cp "${extracted_folder}/hx" "$dest_binary" + chmod +x "$dest_binary" + + # 2) λŸ°νƒ€μž„(runtime) 디렉토리 μ„€μΉ˜ + # ν…Œλ§ˆ, ꡬ문 κ°•μ‘° 트리 등을 λ‘œλ“œν•˜κΈ° μœ„ν•΄ HelixλŠ” runtime 디렉토리가 ν•„μˆ˜μ μž…λ‹ˆλ‹€. + local dest_runtime="${HELIX_CONFIG_DIR}/runtime" + if [ -d "$dest_runtime" ]; then + warn "κΈ°μ‘΄ Helix λŸ°νƒ€μž„ 디렉토리가 κ°μ§€λ˜μ—ˆμŠ΅λ‹ˆλ‹€: $dest_runtime" + local backup_runtime="${dest_runtime}.bak.$(date +%Y%m%d%H%M%S)" + info "κΈ°μ‘΄ λŸ°νƒ€μž„μ„ λ°±μ—…ν•©λ‹ˆλ‹€: $backup_runtime" + mv "$dest_runtime" "$backup_runtime" + fi + + mkdir -p "$HELIX_CONFIG_DIR" + info "λŸ°νƒ€μž„ 디렉토리 배포 쀑: $dest_runtime" + cp -r "${extracted_folder}/runtime" "$dest_runtime" + + # μž„μ‹œ 디렉토리 μ²­μ†Œ + rm -rf "$tmp_dir" + + success "Helix 에디터 ($tag) μ„€μΉ˜κ°€ μ„±κ³΅μ μœΌλ‘œ μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€!" + info "μ‹€ν–‰ λͺ…λ Ήμ–΄: hx" + info "λŸ°νƒ€μž„ 경둜: $dest_runtime" + + # PATH ν™˜κ²½ λ³€μˆ˜ 확인 및 μ•ˆλ‚΄ + if [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; then + warn "μ„€μΉ˜ 경둜($INSTALL_DIR)κ°€ ν˜„μž¬ PATH ν™˜κ²½ λ³€μˆ˜μ— λ“±λ‘λ˜μ–΄ μžˆμ§€ μ•ŠμŠ΅λ‹ˆλ‹€." + warn "μ‚¬μš©ν•˜μ‹œλŠ” μ‰˜ ν”„λ‘œν•„ 파일(예: ~/.bashrc λ˜λŠ” ~/.zshrc)에 μ•„λž˜ 섀정을 μΆ”κ°€ν•΄ μ£Όμ„Έμš”:" + warn " export PATH=\"\$HOME/.local/bin:\$PATH\"" + fi +} + +main "$@"