plum

#treesitter#compiler#wasm

git clone https://git.pyrossh.dev/plum

A statically typed, imperative programming language inspired by rust, python


Makefile.toml
6fc9e6d 1
# Dev-loop tasks for iterating on tree-sitter-plum/plum-lsp without a full
6fc9e6d 2
# `cargo build -p plum-cli` (which re-embeds both into the `plum` binary via
6fc9e6d 3
# build.rs, then still needs a `plum editor <name>` re-run to pick them up).
6fc9e6d 4
# Run with `cargo make <task>` (needs https://github.com/sagiegurari/cargo-make:
6fc9e6d 5
# `cargo install cargo-make`).
6fc9e6d 6
#
6fc9e6d 7
# `plum editor helix`/`plum editor vscode` (the CLI's own install commands)
6fc9e6d 8
# remain the way to set editor support up the first time; `refresh-editors`
6fc9e6d 9
# here only updates whichever of those are already present.
6fc9e6d 10
6fc9e6d 11
[config]
6fc9e6d 12
default_to_workspace = false
6fc9e6d 13
6fc9e6d 14
[tasks.grammar-so]
6fc9e6d 15
description = "Compile the tree-sitter-plum grammar into a native shared library"
6fc9e6d 16
script_runner = "@shell"
6fc9e6d 17
script = '''
6fc9e6d 18
set -e
6fc9e6d 19
SRC=plum-tooling/tree-sitter-plum/src
6fc9e6d 20
OUT=target/plum-grammar.so
6fc9e6d 21
mkdir -p target
6fc9e6d 22
${CC:-cc} -shared -fPIC -O2 -I "$SRC" -o "$OUT" "$SRC/parser.c" "$SRC/scanner.c"
6fc9e6d 23
echo "compiled $OUT"
6fc9e6d 24
'''
6fc9e6d 25
6fc9e6d 26
[tasks.lsp-release]
6fc9e6d 27
description = "Build plum-lsp in release mode"
6fc9e6d 28
command = "cargo"
6fc9e6d 29
args = ["build", "--release", "-p", "plum-lsp"]
6fc9e6d 30
6fc9e6d 31
[tasks.refresh-editors]
6fc9e6d 32
description = "Recompile the grammar + plum-lsp from current source and refresh them in whichever editor configs `plum editor helix`/`plum editor vscode` already set up"
6fc9e6d 33
dependencies = ["grammar-so", "lsp-release"]
6fc9e6d 34
script_runner = "@shell"
6fc9e6d 35
script = '''
6fc9e6d 36
set -e
6fc9e6d 37
LSP_BIN=target/release/plum-lsp
6fc9e6d 38
GRAMMAR_SO=target/plum-grammar.so
6fc9e6d 39
6fc9e6d 40
HELIX_DIR="${HELIX_RUNTIME_CONFIG:-${XDG_CONFIG_HOME:-$HOME/.config}/helix}"
6fc9e6d 41
if [ -f "$HELIX_DIR/languages.toml" ]; then
6fc9e6d 42
  mkdir -p "$HELIX_DIR/runtime/grammars"
6fc9e6d 43
  cp "$GRAMMAR_SO" "$HELIX_DIR/runtime/grammars/plum.so"
6fc9e6d 44
  cp "$LSP_BIN" "$HELIX_DIR/plum-lsp"
6fc9e6d 45
  chmod +x "$HELIX_DIR/plum-lsp"
6fc9e6d 46
  echo "refreshed $HELIX_DIR/runtime/grammars/plum.so"
6fc9e6d 47
  echo "refreshed $HELIX_DIR/plum-lsp"
6fc9e6d 48
else
6fc9e6d 49
  echo "Helix not installed (run \`plum editor helix\` first) — skipping"
6fc9e6d 50
fi
6fc9e6d 51
6fc9e6d 52
# Extension id/version must match plum-cli/src/editor.rs's VSCODE_PUBLISHER /
6fc9e6d 53
# VSCODE_EXTENSION_NAME / VSCODE_EXTENSION_VERSION consts.
6fc9e6d 54
found_vscode=0
6fc9e6d 55
for dir_name in .vscode .vscode-insiders; do
6fc9e6d 56
  ext_dir="$HOME/$dir_name/extensions/plum-lang.plum-0.0.1"
6fc9e6d 57
  if [ -d "$ext_dir" ]; then
6fc9e6d 58
    mkdir -p "$ext_dir/server"
6fc9e6d 59
    cp "$LSP_BIN" "$ext_dir/server/plum-lsp"
6fc9e6d 60
    chmod +x "$ext_dir/server/plum-lsp"
6fc9e6d 61
    echo "refreshed $ext_dir/server/plum-lsp"
6fc9e6d 62
    found_vscode=1
6fc9e6d 63
  fi
6fc9e6d 64
done
6fc9e6d 65
if [ "$found_vscode" = "0" ]; then
6fc9e6d 66
  echo "VSCode not installed (run \`plum editor vscode\` first) — skipping"
6fc9e6d 67
fi
6fc9e6d 68
'''
a473b02 69
a473b02 70
# ---- release binaries -------------------------------------------------------
a473b02 71
#
a473b02 72
# Only the `plum` binary itself is distributed — `plum-lsp`, the tree-sitter
a473b02 73
# grammar `.so`, and the VSCode extension bundle are all embedded INTO it by
a473b02 74
# plum-cli/build.rs already, and `plum editor helix`/`vscode` extract them at
a473b02 75
# install time. There's nothing separate to ship.
a473b02 76
#
a473b02 77
# Linux/Windows are cross-compiled via https://github.com/cross-rs/cross
a473b02 78
# (`cargo install cross --git https://github.com/cross-rs/cross`, needs
a473b02 79
# Docker) — it ships a proper per-target C toolchain (gcc-multilib for Linux,
a473b02 80
# mingw-w64 for Windows), which a bare `cargo build --target ...` doesn't have
a473b02 81
# and this project needs (tree-sitter's scanner.c/parser.c are compiled via
a473b02 82
# the `cc` crate). macOS still builds natively since that's what's running
a473b02 83
# this Makefile.
a473b02 84
#
a473b02 85
# `cargo make release` is the one-shot version: builds all 3 platforms, tags
a473b02 86
# v<version> locally, regenerates README.md's download links, and uploads
a473b02 87
# everything to R2. Version comes from plum-cli/Cargo.toml — bump that first.
a473b02 88
a473b02 89
[env]
a473b02 90
PLUM_VERSION = { script = ["grep -m1 '^version' plum-cli/Cargo.toml | sed -E 's/version = \"(.*)\"/\\1/'"] }
a473b02 91
a473b02 92
[tasks.dist-macos]
a473b02 93
description = "Build a release plum-cli binary for this Mac into dist/plum-cli/"
a473b02 94
script_runner = "@shell"
a473b02 95
script = '''
a473b02 96
set -e
a473b02 97
cargo build --release -p plum-cli
a473b02 98
mkdir -p dist/plum-cli
a473b02 99
ARCH=$(uname -m)
a473b02 100
case "$ARCH" in
a473b02 101
  arm64|aarch64) ARCH=arm64 ;;
a473b02 102
  x86_64) ARCH=x86_64 ;;
a473b02 103
esac
a473b02 104
OUT="dist/plum-cli/plum-darwin-$ARCH"
a473b02 105
cp target/release/plum "$OUT"
a473b02 106
echo "built $OUT"
a473b02 107
'''
a473b02 108
a473b02 109
[tasks.dist-linux]
a473b02 110
description = "Cross-build a release plum-cli binary for Linux x86_64 (via `cross`) into dist/plum-cli/"
a473b02 111
script_runner = "@shell"
a473b02 112
script = '''
a473b02 113
set -e
a473b02 114
cross build --release -p plum-cli --target x86_64-unknown-linux-gnu
a473b02 115
mkdir -p dist/plum-cli
a473b02 116
cp target/x86_64-unknown-linux-gnu/release/plum dist/plum-cli/plum-linux-x86_64
a473b02 117
echo "built dist/plum-cli/plum-linux-x86_64"
a473b02 118
'''
a473b02 119
a473b02 120
[tasks.dist-windows]
a473b02 121
description = "Cross-build a release plum-cli binary for Windows x86_64 (via `cross`) into dist/plum-cli/"
a473b02 122
script_runner = "@shell"
a473b02 123
script = '''
a473b02 124
set -e
a473b02 125
cross build --release -p plum-cli --target x86_64-pc-windows-gnu
a473b02 126
mkdir -p dist/plum-cli
a473b02 127
cp target/x86_64-pc-windows-gnu/release/plum.exe dist/plum-cli/plum-windows-x86_64.exe
a473b02 128
echo "built dist/plum-cli/plum-windows-x86_64.exe"
a473b02 129
'''
a473b02 130
a473b02 131
[tasks.dist-all]
a473b02 132
description = "Build release plum-cli binaries for macOS, Linux, and Windows into dist/plum-cli/"
a473b02 133
dependencies = ["dist-macos", "dist-linux", "dist-windows"]
a473b02 134
a473b02 135
[tasks.tag-release]
a473b02 136
description = "Create a local git tag v<version> (from plum-cli/Cargo.toml) for this release, if it doesn't already exist"
a473b02 137
script_runner = "@shell"
a473b02 138
script = '''
a473b02 139
set -e
a473b02 140
TAG="v${PLUM_VERSION}"
a473b02 141
if git rev-parse "$TAG" >/dev/null 2>&1; then
a473b02 142
  echo "tag $TAG already exists, skipping"
a473b02 143
else
a473b02 144
  git tag -a "$TAG" -m "plum-cli $TAG"
a473b02 145
  echo "created tag $TAG locally — push it yourself with: git push origin $TAG"
a473b02 146
fi
a473b02 147
'''
a473b02 148
a473b02 149
[tasks.update-readme]
a473b02 150
description = "Rewrite README.md's prebuilt-binaries block (between the <!-- prebuilt-binaries:... --> markers) to point at the current version"
a473b02 151
script_runner = "@shell"
a473b02 152
script = '''
a473b02 153
set -e
a473b02 154
BASE="https://git.pyrossh.dev/releases/plum-cli/v${PLUM_VERSION}"
a473b02 155
awk -v base="$BASE" '
a473b02 156
  /<!-- prebuilt-binaries:start -->/ {
a473b02 157
    print
a473b02 158
    print "| Platform | Download |"
a473b02 159
    print "| --- | --- |"
a473b02 160
    print "| macOS (Apple Silicon) | [plum-darwin-arm64](" base "/plum-darwin-arm64) |"
a473b02 161
    print "| Linux (x86_64) | [plum-linux-x86_64](" base "/plum-linux-x86_64) |"
a473b02 162
    print "| Windows (x86_64) | [plum-windows-x86_64.exe](" base "/plum-windows-x86_64.exe) |"
a473b02 163
    print ""
a473b02 164
    print "Make it executable and put it on your `PATH`, e.g. on macOS/Linux:"
a473b02 165
    print ""
a473b02 166
    print "```sh"
a473b02 167
    print "curl -L -o plum " base "/plum-darwin-arm64"
a473b02 168
    print "chmod +x plum"
a473b02 169
    print "mv plum ~/.cargo/bin/plum   # or anywhere else already on your PATH"
a473b02 170
    print "```"
a473b02 171
    in_block = 1
a473b02 172
    next
a473b02 173
  }
a473b02 174
  /<!-- prebuilt-binaries:end -->/ { in_block = 0 }
a473b02 175
  in_block == 1 { next }
a473b02 176
  { print }
a473b02 177
' README.md > README.md.tmp
a473b02 178
mv README.md.tmp README.md
a473b02 179
echo "updated README.md prebuilt-binaries links to v${PLUM_VERSION}"
a473b02 180
'''
a473b02 181
a473b02 182
[tasks.release]
a473b02 183
description = "Build macOS/Linux/Windows release binaries, tag v<version>, update README download links, and upload all 3 to R2 (requires the `git` rclone remote — see `rclone config show git`)"
a473b02 184
dependencies = ["dist-all", "tag-release", "update-readme"]
a473b02 185
script_runner = "@shell"
a473b02 186
script = '''
a473b02 187
set -e
a473b02 188
# `--s3-no-check-bucket`: the R2 access token here is scoped to this one
a473b02 189
# bucket with no ListBuckets/CreateBucket permission, so rclone's default
a473b02 190
# "does this bucket exist?" preflight (which needs one of those) fails —
a473b02 191
# skip it and assume the bucket (already created out-of-band) exists.
a473b02 192
rclone copy dist/plum-cli/ "git:git/releases/plum-cli/v${PLUM_VERSION}/" --s3-no-check-bucket --progress
a473b02 193
echo ""
a473b02 194
echo "published v${PLUM_VERSION}. Remaining steps:"
a473b02 195
echo "  git add README.md && git commit -m \"release v${PLUM_VERSION}\""
a473b02 196
echo "  git push && git push origin v${PLUM_VERSION}"
a473b02 197
'''