This repository has been archived on 2026-08-16. You can view files and clone it, but cannot push or open issues or pull requests.
ollie-acme/scripts/Kmpl

114 lines
4.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# Kmpl: acme glue for u/complete. Triggers completion and prints result to stdout.
set -euo pipefail
cmd=${0##*/}
die() { printf '%s: %s\n' "$cmd" "$*" >&2; exit 1; }
try() { "$@" 2>/dev/null || { ollie-remount && "$@"; }; }
[ -z "${winid:-}" ] || [ "$winid" = "0" ] && die "must be run from an acme window"
# Get filename from tag
filename=$(9p read acme/$winid/tag | awk '{print $1; exit}')
# Read dot position (char offsets)
addr=$(printf 'addr=dot' | 9p write acme/$winid/ctl | 9p read acme/$winid/addr)
read -r q0 q1 <<< "$addr"
[ -z "$q1" ] && q1=$q0
# prefix = BOF to q0, suffix = q1 to EOF, selection = rdsel
prefix=$(printf '#0,#%s' "$q0" | 9p write acme/$winid/addr | 9p read acme/$winid/data)
suffix=$(printf '#%s,$' "$q1" | 9p write acme/$winid/addr | 9p read acme/$winid/data)
sel=$(9p read acme/$winid/rdsel 2>/dev/null || true)
# Compute cursor line/col for LSP calls
line=$(printf '%s' "$prefix" | wc -l)
[ "$line" -eq 0 ] && line=1
col=$(printf '%s' "$prefix" | tail -1 | wc -m)
# Gather LSP context in parallel
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
python3 $OLLIE_TOOLS_PATH/lsp_completion "$filename" "$line" "$col" > "$tmpdir/completions" 2>/dev/null &
python3 $OLLIE_TOOLS_PATH/lsp_symbols "$filename" > "$tmpdir/symbols" 2>/dev/null &
python3 $OLLIE_TOOLS_PATH/lsp_hover "$filename" "$line" "$col" > "$tmpdir/hover" 2>/dev/null &
python3 $OLLIE_TOOLS_PATH/lsp_diagnostics "$filename" > "$tmpdir/diagnostics" 2>/dev/null &
wait
# Walk up to workspace root (parent of .git)
modroot=$(dirname "$filename")
while [ "$modroot" != "/" ]; do
[ -e "$modroot/.git" ] && { modroot=$(dirname "$modroot"); break; }
modroot=$(dirname "$modroot")
done
[ "$modroot" = "/" ] && modroot=$(dirname "$filename")
# Resolve referenced types from hover + selection (iterative, up to 3 levels deep)
{
[ -s "$tmpdir/hover" ] && cat "$tmpdir/hover"
printf '%s\n' "$sel"
} > "$tmpdir/hover_cur"
if [ -s "$tmpdir/hover_cur" ]; then
touch "$tmpdir/hover_embedded" "$tmpdir/seen_types"
for _depth in 1 2 3; do
sed -n 's/.*\[\]\*\?\([A-Z][A-Za-z0-9_]*\).*/\1/p; s/.*\*\([A-Z][A-Za-z0-9_]*\).*/\1/p; s/.*[a-z]\+\.\([A-Z][A-Za-z0-9_]*\).*/\1/p' "$tmpdir/hover_cur" \
| grep -vE '^(MessageState|UnknownFields|SizeCache)$' \
| sort -u > "$tmpdir/new_types" || true
# Remove already-seen types
comm -23 "$tmpdir/new_types" "$tmpdir/seen_types" > "$tmpdir/todo_types" || true
[ -s "$tmpdir/todo_types" ] || break
cat "$tmpdir/todo_types" >> "$tmpdir/seen_types"
sort -u -o "$tmpdir/seen_types" "$tmpdir/seen_types"
> "$tmpdir/hover_cur"
while IFS= read -r etype; do
# Find type reference in current file, then jump to definition
ref=$(grep -n "\b${etype}\b" "$filename" 2>/dev/null | head -1 || true)
[ -z "$ref" ] && continue
rline=${ref%%:*}
rcol=$(sed -n "${rline}p" "$filename" 2>/dev/null | grep -bo "\b${etype}\b" | head -1 | cut -d: -f1 || echo 0)
rcol=$((rcol + 1))
defn=$(python3 $OLLIE_TOOLS_PATH/lsp_definition "$filename" "$rline" "$rcol" 2>/dev/null | head -1 || true)
[ -z "$defn" ] && continue
dfile=${defn%%:*}
dline=$(echo "$defn" | cut -d: -f2)
dcol=$(echo "$defn" | cut -d: -f3)
result=$(try python3 $OLLIE/t/lsp_hover "$dfile" "$dline" "$dcol" || true)
[ -n "$result" ] && [ "$result" != "(no hover info)" ] && { printf '%s\n' "$result" | tee -a "$tmpdir/hover_embedded" >> "$tmpdir/hover_cur"; continue; }
# Fallback: read raw source block
sed -n "${dline},/^}/p" "$dfile" 2>/dev/null | tee -a "$tmpdir/hover_embedded" >> "$tmpdir/hover_cur" || true
done < "$tmpdir/todo_types"
done
fi
context=""
[ -s "$tmpdir/completions" ] && context="${context}<completions>
$(cat "$tmpdir/completions")
</completions>
"
[ -s "$tmpdir/symbols" ] && context="${context}<symbols>
$(cat "$tmpdir/symbols")
</symbols>
"
[ -s "$tmpdir/hover" ] && context="${context}<hover>
$(cat "$tmpdir/hover")
</hover>
"
[ -s "$tmpdir/diagnostics" ] && context="${context}<diagnostics>
$(head -20 "$tmpdir/diagnostics")
</diagnostics>
"
[ -s "$tmpdir/hover_embedded" ] && context="${context}<types>
$(cat "$tmpdir/hover_embedded")
</types>
"
# Send prefix+selection as prefix context; selection is the focal point
_input=$(printf '%s%s' "$prefix" "$sel")
result=$(printf '%s' "$_input" | ${OLLIE_CFG_PATH:-$HOME/.config/ollie}/scripts/u/complete -file "$filename" -suffix "$suffix" -context "$context" -cwd "$modroot" "$@") || {
ollie-remount
result=$(printf '%s' "$_input" | ${OLLIE_CFG_PATH:-$HOME/.config/ollie}/scripts/u/complete -file "$filename" -suffix "$suffix" -context "$context" -cwd "$modroot" "$@")
}
printf '%s' "$result"