Files
nuwiki/development/start-vim.sh
T

388 lines
8.9 KiB
Bash
Raw Normal View History

#!/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" <<EOF
" start-vim.sh: generated minimal config for nuwiki development.
" Regenerated on every launch; edit start-vim.sh, not this file.
" Confine state to the dev cache so we never touch the user's real Vim
" install.
set viminfo='100,n$VIM_STATE/viminfo
let &directory = '$VIM_STATE/swap//'
let &backupdir = '$VIM_STATE/backup//'
let &undodir = '$VIM_STATE/undo//'
" Make Vim look for runtime paths in the dev cache.
set nocompatible
let &runtimepath = '$REPO_ROOT' . ',' . &runtimepath
let &runtimepath .= ',$VIM_LSP_DIR'
let &runtimepath .= ',$ASYNC_DIR'
let g:nuwiki_binary_path = '$REPO_ROOT/bin/nuwiki-ls'
let g:nuwiki_wiki_root = '$WIKI_DIR'
let g:nuwiki_file_extension = '.wiki'
let g:nuwiki_syntax = 'vimwiki'
let g:nuwiki_log_level = 'info'
filetype plugin indent on
syntax enable
set hidden
set termguicolors
set number
set signcolumn=yes
set noswapfile
set nobackup
set nowritebackup
let mapleader = ' '
" Auto-detect filetype for .wiki files (the plugin ships ftdetect, but
" --clean disables those — copy the rule here).
augroup NuwikiFtdetect
autocmd!
autocmd BufRead,BufNewFile *.wiki setfiletype vimwiki
augroup END
" If vim-lsp is on the runtimepath, the plugin's autoload entry point
" registers the server automatically. Triggering it on FileType keeps
" the script's responsibility minimal.
augroup NuwikiStart
autocmd!
autocmd FileType vimwiki call nuwiki#lsp#start()
augroup END
" Status messages go to :messages so they don't trigger "Press ENTER".
echomsg '[nuwiki-dev] ready — wiki root: $WIKI_DIR'
echomsg '[nuwiki-dev] :LspStatus for diagnostics, :messages for log'
EOF
}
main() {
ensure_binary
ensure_vim_lsp
seed_wiki
write_vimrc
mkdir -p "$VIM_STATE/swap" "$VIM_STATE/backup" "$VIM_STATE/undo"
log "launching: vim --clean -u $VIMRC"
if [[ $# -gt 0 ]]; then
exec vim --clean -u "$VIMRC" "$@"
else
exec vim --clean -u "$VIMRC" "$WIKI_DIR/index.wiki"
fi
}
main "$@"