#!/usr/bin/env bash # # start-vim.sh — launch Vim with a minimal config that loads nuwiki. # # The plugin's Vim path (autoload/nuwiki/lsp.vim) prefers `vim-lsp` and # falls back to `coc.nvim`. This script clones vim-lsp + async.vim into # the dev cache on first run so the LSP integration is exercisable # without polluting your real Vim install. # # Usage: ./development/start-vim.sh [extra args...] # ./development/start-vim.sh # open the scratch wiki's index # ./development/start-vim.sh path/to/note.wiki # open a specific file # NUWIKI_DEV_WIKI=/tmp/foo ./development/start-vim.sh # NUWIKI_DEV_NO_LSP=1 ./development/start-vim.sh # skip vim-lsp setup # NUWIKI_DEV_NO_SEED=1 ./development/start-vim.sh # use WIKI_DIR as-is (no scratch seeding) # NUWIKI_DEV_SKIP_BUILD=1 ./development/start-vim.sh # reuse the cached binary # # The release binary is rebuilt on every launch so source changes # always reach the running LSP. `cargo build --release` is incremental, # so this is a fast no-op when nothing changed. Set # NUWIKI_DEV_SKIP_BUILD=1 to skip the build step entirely. # # Tested with Vim 9.1+. State (viminfo/sessions) lives under # $XDG_CACHE_HOME/nuwiki-dev/ so your real Vim install stays untouched. set -euo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" DEV_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/nuwiki-dev" WIKI_DIR="${NUWIKI_DEV_WIKI:-$DEV_DIR/wiki}" VIMRC="$DEV_DIR/vimrc" VIM_STATE="$DEV_DIR/vim-state" VIM_LSP_DIR="$DEV_DIR/vim-lsp" ASYNC_DIR="$DEV_DIR/async.vim" log() { printf '\033[1;34m[nuwiki-dev]\033[0m %s\n' "$*"; } ensure_binary() { local bin="$REPO_ROOT/bin/nuwiki-ls" local built="$REPO_ROOT/target/release/nuwiki-ls" if [[ "${NUWIKI_DEV_SKIP_BUILD:-0}" == "1" ]]; then if [[ ! -x "$bin" ]]; then log "NUWIKI_DEV_SKIP_BUILD=1 but $bin is missing — building anyway" else log "NUWIKI_DEV_SKIP_BUILD=1 — using existing $bin" return fi fi log "building nuwiki-ls (release)…" cargo build --release -p nuwiki-ls --manifest-path "$REPO_ROOT/Cargo.toml" mkdir -p "$REPO_ROOT/bin" ln -sf "$built" "$bin" log "binary ready: $bin (built $(date -r "$built" '+%Y-%m-%d %H:%M:%S'))" } clone_if_missing() { local repo_url="$1" local dest="$2" if [[ -d "$dest/.git" ]]; then return fi if ! command -v git >/dev/null 2>&1; then log "git not found — skipping $repo_url" return 1 fi log "cloning $repo_url → $dest" git clone --depth 1 "$repo_url" "$dest" >/dev/null 2>&1 } ensure_vim_lsp() { if [[ "${NUWIKI_DEV_NO_LSP:-0}" == "1" ]]; then log "NUWIKI_DEV_NO_LSP=1 — skipping vim-lsp setup" return fi mkdir -p "$DEV_DIR" clone_if_missing https://github.com/prabirshrestha/vim-lsp.git "$VIM_LSP_DIR" || true clone_if_missing https://github.com/prabirshrestha/async.vim.git "$ASYNC_DIR" || true } # write_sample_wiki DIR — lay down a fixture that exercises every vimwiki # feature nuwiki supports: one page per feature group plus a diary. Kept # identical to the copy in start-nvim.sh so both launchers showcase the # same surface. Heredocs use a quoted delimiter so `$math`, backticks, # and backslashes land verbatim. write_sample_wiki() { local root="$1" mkdir -p "$root" "$root/diary" cat > "$root/index.wiki" <<'EOF' = nuwiki sample wiki = %% Generated by the start-* dev launchers. A single fixture that exercises %% every vimwiki feature nuwiki supports — open the linked pages and run %% the plugin commands against them. One page per feature group: - [[Syntax]] — inline formatting, blocks, comments - [[Lists]] — bullets, ordering, checkbox states, nesting - [[Tables]] — alignment and spanning cells - [[Links]] — every wikilink and URL form - [[Notes]] — anchor targets for cross-page links - [[diary/diary]] — the diary index === Heading level 3 === ==== Heading level 4 ==== ===== Heading level 5 ===== ====== Heading level 6 ====== == Commands to try == - :NuwikiTOC - :NuwikiGenerateLinks - :NuwikiCheckLinks - :NuwikiMakeDiaryNote :sample:smoke-test:sandbox: EOF cat > "$root/Syntax.wiki" <<'EOF' = Syntax showcase = Back to [[index]]. == Inline formatting == *bold*, _italic_, *_bold italic_*, ~~strikethrough~~, `inline code`, super^script^ and sub,,script,,, and inline math $e^{i\pi} + 1 = 0$. == Keywords == TODO STARTED FIXME XXX DONE FIXED STOPPED == Horizontal rule == ---- == Blockquote == > A quoted line. > A second quoted line. == Definition list == Term:: Definition of the term. Another:: Its definition. == Code block == {{{python def greet(name): return f"hello {name}" }}} == Math block == {{$ \sum_{i=1}^{n} i = \frac{n(n+1)}{2} }}$ == Comments == %% a single-line comment %%+ a multi-line comment block +%% == Transclusion == {{file:image.png}} {{image.png|alt text|width=120}} EOF cat > "$root/Lists.wiki" <<'EOF' = Lists = Back to [[index]]. == Unordered == - item with dash - second - nested under dash * item with star # item with hash == Ordered == 1. first 2. second 1. nested ordered 1) paren style a) alpha A) Alpha i) roman I) Roman == Checkbox states == - [ ] empty (0%) - [.] started (1-33%) - [o] in progress (34-66%) - [O] nearly done (67-99%) - [X] done (100%) - [-] rejected == Nested with checkboxes == - [ ] parent task - [X] done subtask - [ ] pending subtask - [ ] deep subtask EOF cat > "$root/Tables.wiki" <<'EOF' = Tables = Back to [[index]]. == Plain == | Name | Role | | Alice | Author | | Bob | Editor | == Aligned == | Left | Center | Right | |:-----|:------:|------:| | a | b | c | | d | e | f | == Spanning cells == | Header | Span | | cell | > | | rowspan | value | | \/ | value | EOF cat > "$root/Links.wiki" <<'EOF' = Links = Back to [[index]]. == Wikilinks == - [[Notes]] - [[Notes|described]] - [[Notes#Section one]] - [[Notes#Section one|anchored + described]] - [[/index]] - [[diary/]] - [[#Wikilinks]] == Diary and interwiki == - [[diary:2026-05-30]] - [[wiki1:index]] - [[wn.MyWiki:index]] == External and raw URLs == - [[https://example.com]] - [[https://example.com|Example]] - https://example.com - mailto:gffranco@gmail.com - file:///etc/hosts EOF cat > "$root/Notes.wiki" <<'EOF' = Notes = A page that other pages point at. Back to [[index]]. == Section one == Anchor target for cross-page links. == Section two == Another anchor target. EOF cat > "$root/diary/diary.wiki" <<'EOF' = Diary = Back to [[/index]]. - [[2026-05-30]] EOF cat > "$root/diary/2026-05-30.wiki" <<'EOF' = 2026-05-30 = A diary entry. Back to [[diary]]. - [X] set up sample wiki - [ ] review every feature page EOF } seed_wiki() { if [[ "${NUWIKI_DEV_NO_SEED:-0}" == "1" ]]; then log "NUWIKI_DEV_NO_SEED=1 — skipping wiki seed (using $WIKI_DIR as-is)" return fi # Seed the whole showcase as a unit; skip when an index already exists # so a re-run never clobbers edits made while testing. if [[ -f "$WIKI_DIR/index.wiki" ]]; then return fi write_sample_wiki "$WIKI_DIR" } write_vimrc() { mkdir -p "$DEV_DIR" cat > "$VIMRC" <