" scripts/download_bin.vim — install `nuwiki-ls` from a release tarball, " falling back to `cargo build --release` from the nuwiki-rs repo. " " Invoked by Dein / vim-plug build hooks: " vim -e -s -c "source scripts/download_bin.vim" -c "q" " " That invocation runs in 'compatible' mode, where leading-backslash line " continuations aren't recognised (they'd raise E10, and any error in silent " Ex mode makes Vim exit non-zero — a spurious build failure). Reset " 'cpoptions' to the Vim default for the duration so the script parses, and " restore it at the end. let s:cpo_save = &cpo set cpo&vim let s:plugin_dir = fnamemodify(resolve(expand(':p')), ':h:h') let s:bin_dir = s:plugin_dir . '/bin' let s:suffix = has('win32') ? '.exe' : '' let s:bin = s:bin_dir . '/nuwiki-ls' . s:suffix let s:rs_repo = fnamemodify(s:plugin_dir, ':h:h') . '/nuwiki-rs' call mkdir(s:bin_dir, 'p') function! s:is_musl(arch) abort if filereadable('/lib/ld-musl-' . a:arch . '.so.1') return 1 endif if !executable('ldd') return 0 endif " musl's ldd writes its banner to stderr. return stridx(system('ldd --version 2>&1'), 'musl') >= 0 endfunction " NixOS and Guix System are not FHS distributions: glibc lives in the store, " so the /lib64/ld-linux-*.so.2 a generic -gnu binary is linked against is " either absent or — on NixOS — a stub that only prints an error and exits " 127. `ldd --version` still reports GNU libc there, so libc detection alone " picks the wrong asset. The musl builds are statically linked and need no " loader at all, so they run on these systems unchanged. function! s:is_non_fhs_linux() abort if filereadable('/etc/NIXOS') return 1 endif if !filereadable('/etc/os-release') return 0 endif for l:line in readfile('/etc/os-release') let l:id = matchstr(l:line, '^ID=\s*"\?\zs[[:alnum:]._-]\+') if l:id ==# 'nixos' || l:id ==# 'guix' return 1 endif endfor return 0 endfunction " Release triples to try, best first. More than one entry means the later ones " are fallbacks for a host that turns out not to be able to run the first. function! s:targets() abort if get(g:, 'nuwiki_ls_target', '') !=# '' return [g:nuwiki_ls_target] endif if has('win32') return ['x86_64-pc-windows-msvc'] elseif has('mac') return [has('arm64') ? 'aarch64-apple-darwin' : 'x86_64-apple-darwin'] elseif has('linux') let l:uname_m = trim(system('uname -m')) let l:arch = (l:uname_m ==# 'aarch64' || l:uname_m ==# 'arm64') \ ? 'aarch64' : 'x86_64' let l:musl = l:arch . '-unknown-linux-musl' if s:is_musl(l:arch) || s:is_non_fhs_linux() return [l:musl] endif " Static musl runs anywhere, so keep it as a last resort on glibc hosts " too (old glibc, exotic loader layouts). return [l:arch . '-unknown-linux-gnu', l:musl] endif return [] endfunction " Can this host actually start the binary? Exit codes 126 and 127 mean the " kernel or the dynamic loader refused to exec it (missing/stub loader, wrong " architecture); any other code means it ran and exited on its own terms. " system() gives the child an empty stdin, so the LSP loop sees EOF and stops. function! s:can_exec(path) abort call system(shellescape(a:path) . ' --version') return v:shell_error != 126 && v:shell_error != 127 endfunction function! s:build_from_source() abort if !executable('cargo') echohl ErrorMsg | echom 'nuwiki: cargo not found, cannot build from source' | echohl None return 0 endif echom 'nuwiki: cloning nuwiki-rs …' if !filereadable(s:rs_repo . '/Cargo.toml') call system('git clone --depth 1 https://code.gfran.co/gffranco/nuwiki-rs.git ' . shellescape(s:rs_repo)) if v:shell_error != 0 echohl ErrorMsg | echom 'nuwiki: failed to clone nuwiki-rs' | echohl None return 0 endif endif echom 'nuwiki: cargo build --release …' call system('cargo build --release -p nuwiki-ls --manifest-path ' . shellescape(s:rs_repo . '/Cargo.toml')) if v:shell_error != 0 echohl ErrorMsg | echom 'nuwiki: cargo build failed' | echohl None return 0 endif let l:built = s:rs_repo . '/target/release/nuwiki-ls' . s:suffix call system('cp ' . shellescape(l:built) . ' ' . shellescape(s:bin)) call system('chmod +x ' . shellescape(s:bin)) return executable(s:bin) endfunction function! s:download_release(target) abort if !executable('curl') || !executable('tar') return 0 endif let l:url = 'https://code.gfran.co/gffranco/nuwiki-rs/releases/download/latest/nuwiki-ls-' \ . a:target . '.tar.gz' let l:archive = tempname() . '.tar.gz' call system('curl -fsSL -o ' . shellescape(l:archive) . ' ' . shellescape(l:url)) if v:shell_error != 0 return 0 endif let l:extract = tempname() call mkdir(l:extract, 'p') call system('tar -xzf ' . shellescape(l:archive) . ' -C ' . shellescape(l:extract)) if v:shell_error != 0 return 0 endif " Vet the staged copy before it becomes the installed one, so a binary this " host cannot exec never lands at s:bin for the LSP client to pick up. let l:staged = l:extract . '/nuwiki-ls' . s:suffix call system('chmod +x ' . shellescape(l:staged)) if !executable(l:staged) || !s:can_exec(l:staged) return 0 endif call system('cp ' . shellescape(l:staged) . ' ' . shellescape(s:bin)) call system('chmod +x ' . shellescape(s:bin)) return executable(s:bin) endfunction let s:installed = 0 for s:t in s:targets() if s:download_release(s:t) echom 'nuwiki: installed ' . s:bin . ' (' . s:t . ')' let s:installed = 1 break endif endfor if !s:installed echohl WarningMsg | echom 'nuwiki: download failed, falling back to source build' | echohl None if !s:build_from_source() echohl ErrorMsg | echom 'nuwiki: install failed' | echohl None endif endif let &cpo = s:cpo_save