From b9a195bc2354a07e1b730fe5076fb94b7e88bee6 Mon Sep 17 00:00:00 2001 From: Ben Lubas Date: Fri, 11 Oct 2024 22:12:17 -0400 Subject: [PATCH 01/11] ref: example using mlua --- .cargo/config.toml | 11 + .github/workflows/luarocks.yaml | 31 ++ .github/workflows/release-please.yaml | 22 + .github/workflows/release.yaml | 81 ---- .github/workflows/template.rockspec | 52 +++ Cargo.lock | 201 ++++----- Cargo.toml | 12 +- blink-cmp-scm-1.rockspec | 44 ++ build-ffi-bindings.sh | 47 -- build.rs | 27 -- flake.nix | 3 +- .../0.2.2-1/doc/CHANGELOG.md | 17 + .../0.2.2-1/doc/LICENSE | 21 + .../0.2.2-1/doc/README.md | 50 +++ .../luarocks-build-rust-mlua-0.2.2-1.rockspec | 14 + .../0.2.2-1/rock_manifest | 15 + lib/luarocks/rocks-5.2/manifest | 25 ++ libblink_cmp_fuzzy.so | 1 + lua/blink/cmp/fuzzy/download.lua | 143 ------ lua/blink/cmp/fuzzy/ffi.lua | 424 ------------------ lua/blink/cmp/fuzzy/ffi.rs | 83 ---- lua/blink/cmp/fuzzy/init.lua | 2 +- lua/blink/cmp/init.lua | 105 ++--- lua/blink/cmp/sources/buffer.lua | 2 +- rust-toolchain.toml | 1 + share/lua/5.2/luarocks/build/rust-mlua.lua | 92 ++++ {lua/blink/cmp/fuzzy => src}/frecency.rs | 1 + {lua/blink/cmp/fuzzy => src}/fuzzy.rs | 60 ++- src/lib.rs | 91 ++++ 29 files changed, 687 insertions(+), 991 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 .github/workflows/luarocks.yaml create mode 100644 .github/workflows/release-please.yaml delete mode 100644 .github/workflows/release.yaml create mode 100644 .github/workflows/template.rockspec create mode 100644 blink-cmp-scm-1.rockspec delete mode 100755 build-ffi-bindings.sh delete mode 100644 build.rs create mode 100644 lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/CHANGELOG.md create mode 100644 lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/LICENSE create mode 100644 lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/README.md create mode 100644 lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/luarocks-build-rust-mlua-0.2.2-1.rockspec create mode 100644 lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/rock_manifest create mode 100644 lib/luarocks/rocks-5.2/manifest create mode 120000 libblink_cmp_fuzzy.so delete mode 100644 lua/blink/cmp/fuzzy/download.lua delete mode 100644 lua/blink/cmp/fuzzy/ffi.lua delete mode 100644 lua/blink/cmp/fuzzy/ffi.rs create mode 100644 share/lua/5.2/luarocks/build/rust-mlua.lua rename {lua/blink/cmp/fuzzy => src}/frecency.rs (99%) rename {lua/blink/cmp/fuzzy => src}/fuzzy.rs (62%) create mode 100644 src/lib.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 000000000..d47f983e4 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,11 @@ +[target.x86_64-apple-darwin] +rustflags = [ + "-C", "link-arg=-undefined", + "-C", "link-arg=dynamic_lookup", +] + +[target.aarch64-apple-darwin] +rustflags = [ + "-C", "link-arg=-undefined", + "-C", "link-arg=dynamic_lookup", +] diff --git a/.github/workflows/luarocks.yaml b/.github/workflows/luarocks.yaml new file mode 100644 index 000000000..4bb52ea3a --- /dev/null +++ b/.github/workflows/luarocks.yaml @@ -0,0 +1,31 @@ + +name: Push to Luarocks + +on: + push: + tags: + - '*' + release: + types: + - created + pull_request: # Test luarocks install without publishing on PR + workflow_dispatch: + +jobs: + luarocks-upload: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Required to count the commits + - name: Get Version + run: echo "LUAROCKS_VERSION=$(git describe --abbrev=0 --tags)" >> $GITHUB_ENV + - name: LuaRocks Upload + uses: nvim-neorocks/luarocks-tag-release@v6 + env: + LUAROCKS_API_KEY: ${{ secrets.LUAROCKS_API_KEY }} + with: + version: ${{ env.LUAROCKS_VERSION }} + template: "./.github/workflows/template.rockspec" + dependencies: | + lua ~> 5.1 diff --git a/.github/workflows/release-please.yaml b/.github/workflows/release-please.yaml new file mode 100644 index 000000000..84321dbbe --- /dev/null +++ b/.github/workflows/release-please.yaml @@ -0,0 +1,22 @@ +--- +permissions: + contents: write + pull-requests: write + +name: Release Please + +on: + workflow_dispatch: + push: + branches: + - main + +jobs: + release: + name: release + runs-on: ubuntu-latest + steps: + - uses: google-github-actions/release-please-action@v4 + with: + release-type: simple + token: ${{ secrets.PAT }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml deleted file mode 100644 index 8d523c224..000000000 --- a/.github/workflows/release.yaml +++ /dev/null @@ -1,81 +0,0 @@ -name: Release - -on: - push: - tags: - - "v*" - -jobs: - build: - name: Build ${{ matrix.target }} - runs-on: ${{ matrix.os }} - permissions: - contents: read - strategy: - matrix: - include: - # Linux builds (statically linked for compatibility, have to use glibc for FFI) - - os: ubuntu-latest - target: x86_64-unknown-linux-gnu - artifact_name: target/x86_64-unknown-linux-gnu/release/libblink_cmp_fuzzy.so - - os: ubuntu-latest - target: aarch64-unknown-linux-gnu - artifact_name: target/aarch64-unknown-linux-gnu/release/libblink_cmp_fuzzy.so - - # macOS builds - - os: macos-latest - target: x86_64-apple-darwin - artifact_name: target/x86_64-apple-darwin/release/libblink_cmp_fuzzy.dylib - - os: macos-latest - target: aarch64-apple-darwin - artifact_name: target/aarch64-apple-darwin/release/libblink_cmp_fuzzy.dylib - - steps: - - uses: actions/checkout@v4 - - - name: Install Rust - run: | - rustup toolchain install nightly - rustup default nightly - rustup target add ${{ matrix.target }} - - - name: Build for Linux - if: contains(matrix.os, 'ubuntu') - run: | - cargo install cross --git https://github.com/cross-rs/cross - RUSTFLAGS="-C target-feature=-crt-static" cross build --release --target ${{ matrix.target }} - mv "${{ matrix.artifact_name }}" "${{ matrix.target }}.so" - - - name: Build for macOS - if: contains(matrix.os, 'macos') - run: | - # Ventura - MACOSX_DEPLOYMENT_TARGET="13" cargo build --release --target ${{ matrix.target }} - mv "${{ matrix.artifact_name }}" "${{ matrix.target }}.dylib" - - - name: Upload artifacts - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.target }} - path: ${{ matrix.target }}.* - - release: - name: Release - needs: build - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - name: Download artifacts - uses: actions/download-artifact@v4 - - - name: Upload Release Assets - uses: softprops/action-gh-release@v2 - with: - name: ${{ github.ref_name }} - tag_name: ${{ github.ref_name }} - token: ${{ github.token }} - files: ./**/* - draft: false - prerelease: false - generate_release_notes: true diff --git a/.github/workflows/template.rockspec b/.github/workflows/template.rockspec new file mode 100644 index 000000000..20351b3f9 --- /dev/null +++ b/.github/workflows/template.rockspec @@ -0,0 +1,52 @@ +local git_ref = '$git_ref' +local modrev = '$modrev' +local specrev = '$specrev' + +local repo_url = '$repo_url' + +rockspec_format = '3.0' +package = '$package' +version = modrev ..'-'.. specrev + +description = { + summary = '$summary', + detailed = $detailed_description, + labels = $labels, + homepage = '$homepage', + $license +} + +dependencies = $dependencies + +build_dependencies = { + 'luarocks-build-rust-mlua', +} + +test_dependencies = $test_dependencies + +source = { + url = repo_url .. '/archive/' .. git_ref .. '.zip', + dir = '$repo_name-' .. '$archive_dir_suffix', +} + +if modrev == 'scm' or modrev == 'dev' then + source = { + url = repo_url:gsub('https', 'git') + } +end + +build = { + type = "rust-mlua", + + modules = { + ["libblink_cmp_fuzzy"] = "blink_cmp_fuzzy", + }, + + install = { + lua = { + ["blink-cmp.init"] = "lua/blink-cmp.lua", + }, + }, + + copy_directories = $copy_directories, +} diff --git a/Cargo.lock b/Cargo.lock index 861af7fc8..fc7d5aa76 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aho-corasick" @@ -11,6 +11,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + [[package]] name = "bincode" version = "1.3.3" @@ -33,32 +39,30 @@ dependencies = [ name = "blink-cmp-fuzzy" version = "0.1.0" dependencies = [ - "c-marshalling", "frizbee", - "generator", "heed", "lazy_static", - "libc", - "lua-marshalling", + "mlua", "regex", "serde", ] +[[package]] +name = "bstr" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" -[[package]] -name = "c-marshalling" -version = "0.2.0" -source = "git+https://github.com/distil/rust_lua_ffi#30820cdc9282c938dbf8e7bb0a1ea31cf56b25a6" -dependencies = [ - "libc", - "quick-error", -] - [[package]] name = "cc" version = "1.1.29" @@ -68,6 +72,12 @@ dependencies = [ "shlex", ] +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "crossbeam-queue" version = "0.3.11" @@ -83,27 +93,6 @@ version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" -[[package]] -name = "derive-c-marshalling-library" -version = "0.1.0" -source = "git+https://github.com/distil/rust_lua_ffi#30820cdc9282c938dbf8e7bb0a1ea31cf56b25a6" -dependencies = [ - "libc", - "quote 0.4.2", - "syn 0.12.15", -] - -[[package]] -name = "derive-lua-marshalling" -version = "0.2.0" -source = "git+https://github.com/distil/rust_lua_ffi#30820cdc9282c938dbf8e7bb0a1ea31cf56b25a6" -dependencies = [ - "derive-c-marshalling-library", - "libc", - "quote 0.4.2", - "syn 0.12.15", -] - [[package]] name = "doxygen-rs" version = "0.4.2" @@ -131,16 +120,6 @@ dependencies = [ "smith_waterman_macro", ] -[[package]] -name = "generator" -version = "2.0.0" -source = "git+https://github.com/distil/rust_lua_ffi#30820cdc9282c938dbf8e7bb0a1ea31cf56b25a6" -dependencies = [ - "parser", - "quote 0.4.2", - "syn 0.12.15", -] - [[package]] name = "heed" version = "0.20.5" @@ -219,21 +198,55 @@ dependencies = [ ] [[package]] -name = "lua-marshalling" -version = "0.3.0" -source = "git+https://github.com/distil/rust_lua_ffi#30820cdc9282c938dbf8e7bb0a1ea31cf56b25a6" +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mlua" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d111deb18a9c9bd33e1541309f4742523bfab01d276bfa9a27519f6de9c11dc7" dependencies = [ - "c-marshalling", - "derive-lua-marshalling", - "lazy_static", - "libc", + "bstr", + "mlua-sys", + "mlua_derive", + "num-traits", + "once_cell", + "rustc-hash", ] [[package]] -name = "memchr" -version = "2.7.4" +name = "mlua-sys" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "ebe026d6bd1583a9cf9080e189030ddaea7e6f5f0deb366a8e26f8a26c4135b8" +dependencies = [ + "cc", + "cfg-if", + "pkg-config", +] + +[[package]] +name = "mlua_derive" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09697a6cec88e7f58a02c7ab5c18c611c6907c8654613df9cc0192658a4fb859" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] [[package]] name = "once_cell" @@ -251,15 +264,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "parser" -version = "0.2.0" -source = "git+https://github.com/distil/rust_lua_ffi#30820cdc9282c938dbf8e7bb0a1ea31cf56b25a6" -dependencies = [ - "quote 0.4.2", - "syn 0.12.15", -] - [[package]] name = "percent-encoding" version = "2.3.1" @@ -294,8 +298,8 @@ checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" dependencies = [ "phf_generator", "phf_shared", - "proc-macro2 1.0.87", - "quote 1.0.37", + "proc-macro2", + "quote", "syn 2.0.79", ] @@ -309,13 +313,10 @@ dependencies = [ ] [[package]] -name = "proc-macro2" -version = "0.2.3" +name = "pkg-config" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0" -dependencies = [ - "unicode-xid", -] +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "proc-macro2" @@ -326,28 +327,13 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quote" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408" -dependencies = [ - "proc-macro2 0.2.3", -] - [[package]] name = "quote" version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ - "proc-macro2 1.0.87", + "proc-macro2", ] [[package]] @@ -394,6 +380,12 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "rustc-hash" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" + [[package]] name = "ryu" version = "1.0.18" @@ -415,8 +407,8 @@ version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ - "proc-macro2 1.0.87", - "quote 1.0.37", + "proc-macro2", + "quote", "syn 2.0.79", ] @@ -449,30 +441,19 @@ name = "smith_waterman_macro" version = "0.1.0" source = "git+https://github.com/saghen/frizbee#d910bec53b867ce06702520c7e05f9862bf78dd9" dependencies = [ - "proc-macro2 1.0.87", - "quote 1.0.37", + "proc-macro2", + "quote", "syn 1.0.109", ] -[[package]] -name = "syn" -version = "0.12.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c97c05b8ebc34ddd6b967994d5c6e9852fa92f8b82b3858c39451f97346dcce5" -dependencies = [ - "proc-macro2 0.2.3", - "quote 0.4.2", - "unicode-xid", -] - [[package]] name = "syn" version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.87", - "quote 1.0.37", + "proc-macro2", + "quote", "unicode-ident", ] @@ -482,8 +463,8 @@ version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ - "proc-macro2 1.0.87", - "quote 1.0.37", + "proc-macro2", + "quote", "unicode-ident", ] @@ -532,12 +513,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" - [[package]] name = "url" version = "2.5.2" diff --git a/Cargo.toml b/Cargo.toml index e98dc4ba5..91f0bdcef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,18 +4,16 @@ version = "0.1.0" edition = "2021" [lib] -path = "lua/blink/cmp/fuzzy/ffi.rs" crate-type = ["cdylib"] +[features] +luajit = ["mlua/luajit"] +lua51 = ["mlua/lua51"] + [dependencies] -libc = "0.2.20" -c-marshalling = { git = "https://github.com/distil/rust_lua_ffi" } -lua-marshalling = { git = "https://github.com/distil/rust_lua_ffi" } regex = "1.10.5" lazy_static = "1.5.0" frizbee = { git = "https://github.com/saghen/frizbee" } serde = { version = "1.0.204", features = ["derive"] } heed = "0.20.3" - -[build-dependencies] -generator = { git = "https://github.com/distil/rust_lua_ffi" } +mlua = { version = "0.9.9", features = ["module"] } diff --git a/blink-cmp-scm-1.rockspec b/blink-cmp-scm-1.rockspec new file mode 100644 index 000000000..cf2fd1bb9 --- /dev/null +++ b/blink-cmp-scm-1.rockspec @@ -0,0 +1,44 @@ +local MODREV, SPECREV = "scm", "-1" +rockspec_format = "3.0" +package = "blink-cmp" +version = MODREV .. SPECREV + +description = { + summary = "Performant, batteries-included completion plugin for Neovim", + labels = { "neovim" }, + homepage = "https://github.com/Saghen/blink.cmp", + license = "MIT", +} + +source = { + url = "http://github.com/Saghen/blink-cmp/archive/v" .. MODREV .. ".zip", +} + +if MODREV == "scm" then + source = { + url = "git://github.com/Saghen/blink-cmp", + } +end + +dependencies = { + "lua = 5.1", +} + +build_dependencies = { + "luarocks-build-rust-mlua", +} + +build = { + type = "rust-mlua", + + modules = { + ["libblink_cmp_fuzzy"] = "blink_cmp_fuzzy", + }, + + install = { + lua = { + ["blink-cmp.init"] = "lua/blink-cmp.lua", + }, + }, + features = { "lua51" } +} diff --git a/build-ffi-bindings.sh b/build-ffi-bindings.sh deleted file mode 100755 index cbaa412b5..000000000 --- a/build-ffi-bindings.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env bash -set -e -cd "$(dirname "$(realpath "$0")")" - -# shellcheck disable=SC2155 -export LD_LIBRARY_PATH="$(pwd)/target/release" -export RUST_LUA_FFI_TYPE_PREFIX=blink_cmp_fuzzy - -cat < "$(pwd)/lua/blink/cmp/fuzzy/bootstrap.lua" -local ffi = require("ffi") - -ffi.cdef([[ - char *__lua_bootstrap(); - void __free_lua_bootstrap(char *); -]]) -local rust = ffi.load(arg[1]) - -local bootstrap = rust.__lua_bootstrap() -if bootstrap == nil then - error("lua_bootstrap failed") -end -ffi.gc(bootstrap, rust.__free_lua_bootstrap) -print(ffi.string(bootstrap)) -EOF - -luajit "$(pwd)/lua/blink/cmp/fuzzy/bootstrap.lua" blink_cmp_fuzzy > "$(pwd)/lua/blink/cmp/fuzzy/ffi.lua" -rm "$(pwd)/lua/blink/cmp/fuzzy/bootstrap.lua" - -# hack: super scuffed way of getting the shared lib extension -# and rewriting the ffi.lua file to point to the correct target dir - -echo " -local function get_shared_lib_extension() - local os = jit.os:lower() - if os == 'osx' or os == 'mac' then - return '.dylib' - elseif os == 'windows' then - return '.dll' - else - return '.so' - end -end - -$(cat "$(pwd)/lua/blink/cmp/fuzzy/ffi.lua") -" > "$(pwd)/lua/blink/cmp/fuzzy/ffi.lua" - -sed -i "s|local rust = ffi\.load('blink-cmp-fuzzy')|local ok, rust = pcall(function() return ffi.load(debug.getinfo(1).source:match('@?(.*/)') .. '../../../../target/release/libblink_cmp_fuzzy' .. get_shared_lib_extension()) end)\nif not ok then\n rust = ffi.load(debug.getinfo(1).source:match('@?(.*/)') .. '../../../../target/release/blink_cmp_fuzzy' .. get_shared_lib_extension())\nend|" "$(pwd)/lua/blink/cmp/fuzzy/ffi.lua" diff --git a/build.rs b/build.rs deleted file mode 100644 index 1123b3192..000000000 --- a/build.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::env; -use std::fs::File; -use std::io::Write; -use std::path::Path; - -fn main() { - let rust_output = Path::new(&env::var("OUT_DIR").unwrap()).join("ffi.rs"); - - let output = generator::generate( - &env::current_dir() - .unwrap() - .as_path() - .join("lua/blink/cmp/fuzzy/ffi.rs"), - "blink-cmp-fuzzy", - false, - ); - - File::create(rust_output.clone()) - .unwrap() - .write_all(output.as_bytes()) - .unwrap(); - - // delete existing version.txt file created by downloader - let _ = std::fs::remove_file("target/release/version.txt"); - - assert!(rust_output.exists()); -} diff --git a/flake.nix b/flake.nix index 7d3a1ce31..cc34b3d94 100644 --- a/flake.nix +++ b/flake.nix @@ -46,8 +46,6 @@ cargoLock = { lockFile = ./Cargo.lock; outputHashes = { - "c-marshalling-0.2.0" = - "sha256-eL6nkZOtuLLQ0r31X7uroUUDYZsWOJ9KNXl4NCVNRuw="; "frizbee-0.1.0" = "sha256-zO2S282DVCjnALMXu3GxmAfjCXsPNUZ7+xgiqITfGmU="; }; @@ -59,6 +57,7 @@ else if hostPlatform.isWindows then "dll" else "so"; in { + # TODO: I'm not sure how this will change blink-cmp = pkgs.vimUtils.buildVimPlugin { pname = "blink-cmp"; inherit src version; diff --git a/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/CHANGELOG.md b/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/CHANGELOG.md new file mode 100644 index 000000000..38ef9a873 --- /dev/null +++ b/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/CHANGELOG.md @@ -0,0 +1,17 @@ +## v0.2.2 + +- Pass correct `target-dir` arg to cargo instead of `target` (mlua-rs/luarocks-build-rust-mlua#12) + +## v0.2.1 (yanked) + +- Pass `target_path` to cargo if it's set (mlua-rs/luarocks-build-rust-mlua#9) +- Re-enable support for LuaRocks 3.1.x (mlua-rs/luarocks-build-rust-mlua#10) + +## v0.2.0 + +This release lines up with the mlua v0.9 changes + +- Do not require lua headers or lib on Windows (modules are linked with `lua5x.dll`) +- Never pass `vendored` feature (makes no sense in the module mode) +- Support `default_features = false` option to pass `--no-default-features` to cargo +- Support `features` option to pass additional features to cargo diff --git a/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/LICENSE b/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/LICENSE new file mode 100644 index 000000000..a78c81b36 --- /dev/null +++ b/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 A. Orlenko + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/README.md b/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/README.md new file mode 100644 index 000000000..f6c87a992 --- /dev/null +++ b/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/README.md @@ -0,0 +1,50 @@ +# luarocks-build-rust-mlua + +A [LuaRocks] build backend for Lua modules written in Rust using [mlua]. + +[LuaRocks]: http://luarocks.org +[mlua]: http://github.com/mlua-rs/mlua + +# Example rockspec + +```lua +package = "my_module" +version = "0.1.0-1" + +source = { + url = "git+https://github.com/username/my_module", + tag = "0.1.0", +} + +description = { + summary = "Example Lua module in Rust", + detailed = "...", + homepage = "https://github.com/username/my_module", + license = "MIT" +} + +dependencies = { + "lua >= 5.1", + "luarocks-build-rust-mlua", +} + +build = { + type = "rust-mlua", + + modules = { + -- Native library expected in `/release/libmy_module.so` (linux; uses right name on macos/windows) + "my_module", + -- More complex case, native library expected in `/release/libalt_name.so` + ["my_module"] = "alt_name", + }, + + -- Optional: target_path if cargo "target" directory not in the module root + target_path = "path/to/cargo/target/directory" + + -- Optional: if set to `false` pass `--no-default-features` to cargo + default_features = false, + + -- Optional: pass additional features + features = {"extra", "features"} +} +``` diff --git a/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/luarocks-build-rust-mlua-0.2.2-1.rockspec b/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/luarocks-build-rust-mlua-0.2.2-1.rockspec new file mode 100644 index 000000000..76a4a4bff --- /dev/null +++ b/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/luarocks-build-rust-mlua-0.2.2-1.rockspec @@ -0,0 +1,14 @@ +rockspec_format = "3.0" +package = "luarocks-build-rust-mlua" +version = "0.2.2-1" + +source = { + url = "git+https://github.com/mlua-rs/luarocks-build-rust-mlua", + tag = "0.2.2", +} + +description = { + summary = "A LuaRocks build backend for Lua modules written in Rust using mlua", + homepage = "https://github.com/mlua-rs/luarocks-build-rust-mlua", + license = "MIT", +} diff --git a/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/rock_manifest b/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/rock_manifest new file mode 100644 index 000000000..777fd1fdb --- /dev/null +++ b/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/rock_manifest @@ -0,0 +1,15 @@ +rock_manifest = { + doc = { + ["CHANGELOG.md"] = "319bd4edc94b46360328e3693edc2448", + LICENSE = "31a0963ca1b66065691cc341103d1e50", + ["README.md"] = "2261bffc33134e7e2f5776ad9e8691a4" + }, + lua = { + luarocks = { + build = { + ["rust-mlua.lua"] = "c0347aec6cfa2cb849f789a10f9281a1" + } + } + }, + ["luarocks-build-rust-mlua-0.2.2-1.rockspec"] = "976b0a28ea6d00733f449c764528bdda" +} diff --git a/lib/luarocks/rocks-5.2/manifest b/lib/luarocks/rocks-5.2/manifest new file mode 100644 index 000000000..8a20c3227 --- /dev/null +++ b/lib/luarocks/rocks-5.2/manifest @@ -0,0 +1,25 @@ +commands = {} +dependencies = { + ["luarocks-build-rust-mlua"] = { + ["0.2.2-1"] = {} + } +} +modules = { + ["luarocks.build.rust-mlua"] = { + "luarocks-build-rust-mlua/0.2.2-1" + } +} +repository = { + ["luarocks-build-rust-mlua"] = { + ["0.2.2-1"] = { + { + arch = "installed", + commands = {}, + dependencies = {}, + modules = { + ["luarocks.build.rust-mlua"] = "luarocks/build/rust-mlua.lua" + } + } + } + } +} diff --git a/libblink_cmp_fuzzy.so b/libblink_cmp_fuzzy.so new file mode 120000 index 000000000..b7f0e2433 --- /dev/null +++ b/libblink_cmp_fuzzy.so @@ -0,0 +1 @@ +./target/release/libblink_cmp_fuzzy.so \ No newline at end of file diff --git a/lua/blink/cmp/fuzzy/download.lua b/lua/blink/cmp/fuzzy/download.lua deleted file mode 100644 index 7a3a31a9b..000000000 --- a/lua/blink/cmp/fuzzy/download.lua +++ /dev/null @@ -1,143 +0,0 @@ -local download_config = require('blink.cmp.config').fuzzy.prebuiltBinaries - -local download = {} - ---- @return string -function download.get_lib_extension() - if jit.os:lower() == 'mac' or jit.os:lower() == 'osx' then return '.dylib' end - if jit.os:lower() == 'windows' then return '.dll' end - return '.so' -end - -local root_dir = debug.getinfo(1).source:match('@?(.*/)') -local lib_path = root_dir .. '../../../../target/release/libblink_cmp_fuzzy' .. download.get_lib_extension() -local version_path = root_dir .. '../../../../target/release/version.txt' - ---- @param callback fun(err: string | nil) -function download.ensure_downloaded(callback) - local function cb(err) - vim.schedule(function() callback(err) end) - end - - if not download_config.download then return cb() end - - download.get_git_tag(function(git_version_err, git_version) - if git_version_err then return cb(git_version_err) end - - download.get_downloaded_version(function(version_err, version) - download.is_downloaded(function(downloaded) - local target_version = download_config.forceVersion or git_version - - -- not built locally, not a git tag, error - if not downloaded and not target_version then - return cb( - "Can't download from github due to not being on a git tag and no fuzzy.prebuiltBinaries.forceVersion set, but found no built version of the library. " - .. 'Either run `cargo build --release` via your package manager, switch to a git tag, or set `fuzzy.prebuiltBinaries.forceVersion` in config. ' - .. 'See the README for more info.' - ) - end - -- built locally, ignore - if downloaded and (version_err or version == nil) then return cb() end - -- already downloaded and the correct version - if version == target_version and downloaded then return cb() end - -- unknown state - if not target_version then return cb('Unknown error while getting pre-built binary. Consider re-installing') end - - -- download from github and set version - download.from_github(target_version, function(download_err) - if download_err then return cb(download_err) end - download.set_downloaded_version(target_version, function(set_err) - if set_err then return cb(set_err) end - cb() - end) - end) - end) - end) - end) -end - ---- @param cb fun(downloaded: boolean) -function download.is_downloaded(cb) - vim.uv.fs_stat(lib_path, function(err) - if not err then - cb(true) - else - -- If not found, check without 'lib' prefix - vim.uv.fs_stat(string.gsub(lib_path, 'libblink_cmp_fuzzy', 'blink_cmp_fuzzy'), function(error) cb(not error) end) - end - end) -end - ---- @param cb fun(err: string | nil, tag: string | nil) -function download.get_git_tag(cb) - vim.system({ 'git', 'describe', '--tags', '--exact-match' }, { cwd = root_dir }, function(out) - if out.code == 128 then return cb() end - if out.code ~= 0 then - return cb('While getting git tag, git exited with code ' .. out.code .. ': ' .. out.stderr) - end - local lines = vim.split(out.stdout, '\n') - if not lines[1] then return cb('Expected atleast 1 line of output from git describe') end - return cb(nil, lines[1]) - end) -end - ---- @param tag string ---- @param cb fun(err: string | nil) -function download.from_github(tag, cb) - local system_triple = download.get_system_triple() - if not system_triple then - return cb( - 'Your system is not supported by pre-built binaries. You must run cargo build --release via your package manager with rust nightly. See the README for more info.' - ) - end - - local url = 'https://github.com/saghen/blink.cmp/releases/download/' - .. tag - .. '/' - .. system_triple - .. download.get_lib_extension() - - vim.system({ 'curl', '--create-dirs', '-Lo', lib_path, url }, {}, function(out) - if out.code ~= 0 then cb('Failed to download pre-build binaries: ' .. out.stderr) end - cb() - end) -end - ---- @param cb fun(err: string | nil, last_version: string | nil) -function download.get_downloaded_version(cb) - return vim.uv.fs_open(version_path, 'r', 438, function(open_err, fd) - if open_err or fd == nil then return cb(open_err or 'Unknown error') end - vim.uv.fs_read(fd, 8, 0, function(read_err, data) - vim.uv.fs_close(fd, function() end) - if read_err or data == nil then return cb(read_err or 'Unknown error') end - return cb(nil, data) - end) - end) -end - ---- @param version string ---- @param cb fun(err: string | nil) -function download.set_downloaded_version(version, cb) - return vim.uv.fs_open(version_path, 'w', 438, function(open_err, fd) - if open_err or fd == nil then return cb(open_err or 'Unknown error') end - vim.uv.fs_write(fd, version, 0, function(write_err) - vim.uv.fs_close(fd, function() end) - if write_err then return cb(write_err) end - return cb() - end) - end) -end - ---- @return string | nil -function download.get_system_triple() - if jit.os:lower() == 'mac' or jit.os:lower() == 'osx' then - if jit.arch:lower():match('arm') then return 'aarch64-apple-darwin' end - if jit.arch:lower():match('x64') then return 'x86_64-apple-darwin' end - end - if jit.os:lower() ~= 'windows' then - if jit.arch:lower():match('arm') then return 'aarch64-unknown-linux-gnu' end - if jit.arch:lower():match('x64') then return 'x86_64-unknown-linux-gnu' end - end -end - -return download diff --git a/lua/blink/cmp/fuzzy/ffi.lua b/lua/blink/cmp/fuzzy/ffi.lua deleted file mode 100644 index 24f81fd3e..000000000 --- a/lua/blink/cmp/fuzzy/ffi.lua +++ /dev/null @@ -1,424 +0,0 @@ - -local function get_shared_lib_extension() - local os = jit.os:lower() - if os == 'osx' or os == 'mac' then - return '.dylib' - elseif os == 'windows' then - return '.dll' - else - return '.so' - end -end - --- Code generated by Rust Lua interface. DO NOT EDIT. - - local ffi = require("ffi") - - ffi.cdef[[ - - - -typedef struct { - const char * *ptr; - size_t len; - size_t capacity; -} blink_cmp_fuzzy__Vec___string_ptr; -typedef struct { - const blink_cmp_fuzzy__Vec___string_ptr *ptr; -} blink_cmp_fuzzy__Option_Vec___string_ptr; - -typedef struct { - const int32_t *ptr; -} blink_cmp_fuzzy__Option_int32_t; - - - - typedef struct { - const int8_t use_frecency; - const blink_cmp_fuzzy__Option_Vec___string_ptr nearby_words; - const uint16_t min_score; - const size_t max_items; - const blink_cmp_fuzzy__Vec___string_ptr sorts; - } blink_cmp_fuzzy__FuzzyOptions; - - -typedef struct { - const uint32_t *ptr; - size_t len; - size_t capacity; -} blink_cmp_fuzzy__Vec_uint32_t; -typedef struct { - const char * *ptr; -} blink_cmp_fuzzy__Option___string_ptr; - - typedef struct { - const char * label; - const blink_cmp_fuzzy__Option___string_ptr sort_text; - const blink_cmp_fuzzy__Option___string_ptr filter_text; - const uint32_t kind; - const blink_cmp_fuzzy__Option_int32_t score_offset; - const char * source; - } blink_cmp_fuzzy__LspItem; - -typedef struct { - const int32_t *ptr; - size_t len; - size_t capacity; -} blink_cmp_fuzzy__Vec_int32_t; -int32_t init_db( - const char *, - int8_t*); -int32_t __gc_init_db( - int8_t); -int32_t destroy_db( - int8_t*); -int32_t __gc_destroy_db( - int8_t); -int32_t access( - const blink_cmp_fuzzy__LspItem*, - int8_t*); -int32_t __gc_access( - int8_t); -int32_t fuzzy( - const char *, - const blink_cmp_fuzzy__Vec___string_ptr*, - const blink_cmp_fuzzy__Vec_uint32_t*, - const blink_cmp_fuzzy__Vec_int32_t*, - const blink_cmp_fuzzy__Vec___string_ptr*, - const blink_cmp_fuzzy__FuzzyOptions*, - blink_cmp_fuzzy__Vec_uint32_t**); -int32_t __gc_fuzzy( - blink_cmp_fuzzy__Vec_uint32_t*); -int32_t get_words( - const char *, - blink_cmp_fuzzy__Vec___string_ptr**); -int32_t __gc_get_words( - blink_cmp_fuzzy__Vec___string_ptr*); - - ]] - - local ok, rust = pcall(function() return ffi.load(debug.getinfo(1).source:match('@?(.*/)') .. '../../../../target/release/libblink_cmp_fuzzy' .. get_shared_lib_extension()) end) -if not ok then - rust = ffi.load(debug.getinfo(1).source:match('@?(.*/)') .. '../../../../target/release/blink_cmp_fuzzy' .. get_shared_lib_extension()) -end - - local M = {} - - - -local __const_c_typename_int32_t = ffi.typeof("const int32_t[?]") -local __c_function_argument_int32_t = ffi.typeof("int32_t[?]") -local __c_mut_function_argument_int32_t = ffi.typeof("int32_t[?]") - - -local __const_c_typename___string_ptr = ffi.typeof("const char *[?]") -local __c_function_argument___string_ptr = ffi.typeof("const char *[?]") -local __c_mut_function_argument___string_ptr = ffi.typeof("char *[?]") - - -local __typename_Vec___string_ptr = ffi.metatype("blink_cmp_fuzzy__Vec___string_ptr", {}) -local __const_c_typename_Vec___string_ptr = ffi.typeof("const blink_cmp_fuzzy__Vec___string_ptr[?]") -local __c_function_argument_Vec___string_ptr = ffi.typeof("const blink_cmp_fuzzy__Vec___string_ptr*[?]") -local __c_mut_function_argument_Vec___string_ptr = ffi.typeof("blink_cmp_fuzzy__Vec___string_ptr*[?]") - - -local __typename_Option_Vec___string_ptr = ffi.metatype("blink_cmp_fuzzy__Option_Vec___string_ptr", {}) -local __const_c_typename_Option_Vec___string_ptr = ffi.typeof("const blink_cmp_fuzzy__Option_Vec___string_ptr[?]") -local __c_function_argument_Option_Vec___string_ptr = ffi.typeof("const blink_cmp_fuzzy__Option_Vec___string_ptr*[?]") -local __c_mut_function_argument_Option_Vec___string_ptr = ffi.typeof("blink_cmp_fuzzy__Option_Vec___string_ptr*[?]") - - -local __const_c_typename_size_t = ffi.typeof("const size_t[?]") -local __c_function_argument_size_t = ffi.typeof("size_t[?]") -local __c_mut_function_argument_size_t = ffi.typeof("size_t[?]") - - -local __typename_Option_int32_t = ffi.metatype("blink_cmp_fuzzy__Option_int32_t", {}) -local __const_c_typename_Option_int32_t = ffi.typeof("const blink_cmp_fuzzy__Option_int32_t[?]") -local __c_function_argument_Option_int32_t = ffi.typeof("const blink_cmp_fuzzy__Option_int32_t*[?]") -local __c_mut_function_argument_Option_int32_t = ffi.typeof("blink_cmp_fuzzy__Option_int32_t*[?]") - - -local __const_c_typename_bool = ffi.typeof("const int8_t[?]") -local __c_function_argument_bool = ffi.typeof("int8_t[?]") -local __c_mut_function_argument_bool = ffi.typeof("int8_t[?]") - - -local __const_c_typename_uint16_t = ffi.typeof("const uint16_t[?]") -local __c_function_argument_uint16_t = ffi.typeof("uint16_t[?]") -local __c_mut_function_argument_uint16_t = ffi.typeof("uint16_t[?]") - - -local __typename_FuzzyOptions = ffi.metatype("blink_cmp_fuzzy__FuzzyOptions", {}) -local __const_c_typename_FuzzyOptions = ffi.typeof("const blink_cmp_fuzzy__FuzzyOptions[?]") -local __c_function_argument_FuzzyOptions = ffi.typeof("const blink_cmp_fuzzy__FuzzyOptions*[?]") -local __c_mut_function_argument_FuzzyOptions = ffi.typeof("blink_cmp_fuzzy__FuzzyOptions*[?]") - - -local __const_c_typename_uint32_t = ffi.typeof("const uint32_t[?]") -local __c_function_argument_uint32_t = ffi.typeof("uint32_t[?]") -local __c_mut_function_argument_uint32_t = ffi.typeof("uint32_t[?]") - - -local __typename_Vec_uint32_t = ffi.metatype("blink_cmp_fuzzy__Vec_uint32_t", {}) -local __const_c_typename_Vec_uint32_t = ffi.typeof("const blink_cmp_fuzzy__Vec_uint32_t[?]") -local __c_function_argument_Vec_uint32_t = ffi.typeof("const blink_cmp_fuzzy__Vec_uint32_t*[?]") -local __c_mut_function_argument_Vec_uint32_t = ffi.typeof("blink_cmp_fuzzy__Vec_uint32_t*[?]") - - -local __typename_Option___string_ptr = ffi.metatype("blink_cmp_fuzzy__Option___string_ptr", {}) -local __const_c_typename_Option___string_ptr = ffi.typeof("const blink_cmp_fuzzy__Option___string_ptr[?]") -local __c_function_argument_Option___string_ptr = ffi.typeof("const blink_cmp_fuzzy__Option___string_ptr*[?]") -local __c_mut_function_argument_Option___string_ptr = ffi.typeof("blink_cmp_fuzzy__Option___string_ptr*[?]") - - -local __typename_LspItem = ffi.metatype("blink_cmp_fuzzy__LspItem", {}) -local __const_c_typename_LspItem = ffi.typeof("const blink_cmp_fuzzy__LspItem[?]") -local __c_function_argument_LspItem = ffi.typeof("const blink_cmp_fuzzy__LspItem*[?]") -local __c_mut_function_argument_LspItem = ffi.typeof("blink_cmp_fuzzy__LspItem*[?]") - - -local __typename_Vec_int32_t = ffi.metatype("blink_cmp_fuzzy__Vec_int32_t", {}) -local __const_c_typename_Vec_int32_t = ffi.typeof("const blink_cmp_fuzzy__Vec_int32_t[?]") -local __c_function_argument_Vec_int32_t = ffi.typeof("const blink_cmp_fuzzy__Vec_int32_t*[?]") -local __c_mut_function_argument_Vec_int32_t = ffi.typeof("blink_cmp_fuzzy__Vec_int32_t*[?]") - -function M.init_db( - db_path) - local __typeof = __c_mut_function_argument_bool - local __ret_ptr = __typeof(1, {}) - local status = rust.init_db( - (function(value) return value end)(db_path), - __ret_ptr - ) - if status ~= 0 then - error("init_db failed with status "..status) - end - local __ret = __ret_ptr[0] - - local f = function(value) return value ~= 0 end - return f(__ret) -end - -function M.destroy_db( - ) - local __typeof = __c_mut_function_argument_bool - local __ret_ptr = __typeof(1, {}) - local status = rust.destroy_db( - __ret_ptr - ) - if status ~= 0 then - error("destroy_db failed with status "..status) - end - local __ret = __ret_ptr[0] - - local f = function(value) return value ~= 0 end - return f(__ret) -end - -function M.access( - item) - local __typeof = __c_mut_function_argument_bool - local __ret_ptr = __typeof(1, {}) - local status = rust.access( - (function(value) - return __typename_LspItem( - (function(value) return value end)(value.label), - ( -function(value) - local f = function(value) - return __const_c_typename___string_ptr(1, { value }) -end - if value ~= nil then - return __typename_Option___string_ptr(f(value)) - else - return __typename_Option___string_ptr(nil) - end -end -)(value.sort_text), - ( -function(value) - local f = function(value) - return __const_c_typename___string_ptr(1, { value }) -end - if value ~= nil then - return __typename_Option___string_ptr(f(value)) - else - return __typename_Option___string_ptr(nil) - end -end -)(value.filter_text), - (function(value) return value end)(value.kind), - ( -function(value) - local f = function(value) - return __const_c_typename_int32_t(1, { value }) -end - if value ~= nil then - return __typename_Option_int32_t(f(value)) - else - return __typename_Option_int32_t(nil) - end -end -)(value.score_offset), - (function(value) return value end)(value.source) - ) - end)(item), - __ret_ptr - ) - if status ~= 0 then - error("access failed with status "..status) - end - local __ret = __ret_ptr[0] - - local f = function(value) return value ~= 0 end - return f(__ret) -end - -function M.fuzzy( - needle, - haystack_labels, - haystack_kinds, - haystack_score_offsets, - haystack_sources, - opts) - local __typeof = __c_mut_function_argument_Vec_uint32_t - local __ret_ptr = __typeof(1, {}) - local status = rust.fuzzy( - (function(value) return value end)(needle), - ( -function(value) - if type(value) == "string" then - return __typename_Vec___string_ptr(value, #value) - else - local f = function(value) - return __const_c_typename___string_ptr(#value, value) -end - return __typename_Vec___string_ptr(f(value), #value, 0) - end -end -)(haystack_labels), - ( -function(value) - if type(value) == "string" then - return __typename_Vec_uint32_t(value, #value) - else - local f = function(value) - return __const_c_typename_uint32_t(#value, value) -end - return __typename_Vec_uint32_t(f(value), #value, 0) - end -end -)(haystack_kinds), - ( -function(value) - if type(value) == "string" then - return __typename_Vec_int32_t(value, #value) - else - local f = function(value) - return __const_c_typename_int32_t(#value, value) -end - return __typename_Vec_int32_t(f(value), #value, 0) - end -end -)(haystack_score_offsets), - ( -function(value) - if type(value) == "string" then - return __typename_Vec___string_ptr(value, #value) - else - local f = function(value) - return __const_c_typename___string_ptr(#value, value) -end - return __typename_Vec___string_ptr(f(value), #value, 0) - end -end -)(haystack_sources), - (function(value) - return __typename_FuzzyOptions( - (function(value) return value and 1 or 0 end)(value.use_frecency), - ( -function(value) - local f = -function(value) - if type(value) == "string" then - return __typename_Vec___string_ptr(value, #value) - else - local f = function(value) - return __const_c_typename___string_ptr(#value, value) -end - return __typename_Vec___string_ptr(f(value), #value, 0) - end -end - - if value ~= nil then - return __typename_Option_Vec___string_ptr(f(value)) - else - return __typename_Option_Vec___string_ptr(nil) - end -end -)(value.nearby_words), - (function(value) return value end)(value.min_score), - (function(value) return value end)(value.max_items), - ( -function(value) - if type(value) == "string" then - return __typename_Vec___string_ptr(value, #value) - else - local f = function(value) - return __const_c_typename___string_ptr(#value, value) -end - return __typename_Vec___string_ptr(f(value), #value, 0) - end -end -)(value.sorts) - ) - end)(opts), - __ret_ptr - ) - if status ~= 0 then - error("fuzzy failed with status "..status) - end - local __ret = __ret_ptr[0] - ffi.gc(__ret, rust.__gc_fuzzy) - local f = function(value) - local ret = {} - local len = tonumber(value.len) - local f = function(value) return value end - for i = 1,len do - ret[i] = f(value.ptr[i - 1]) - end - return ret -end - return f(__ret) -end - -function M.get_words( - text) - local __typeof = __c_mut_function_argument_Vec___string_ptr - local __ret_ptr = __typeof(1, {}) - local status = rust.get_words( - (function(value) return value end)(text), - __ret_ptr - ) - if status ~= 0 then - error("get_words failed with status "..status) - end - local __ret = __ret_ptr[0] - ffi.gc(__ret, rust.__gc_get_words) - local f = function(value) - local ret = {} - local len = tonumber(value.len) - local f = ffi.string - for i = 1,len do - ret[i] = f(value.ptr[i - 1]) - end - return ret -end - return f(__ret) -end - - - return M - - diff --git a/lua/blink/cmp/fuzzy/ffi.rs b/lua/blink/cmp/fuzzy/ffi.rs deleted file mode 100644 index e684e2982..000000000 --- a/lua/blink/cmp/fuzzy/ffi.rs +++ /dev/null @@ -1,83 +0,0 @@ -#![feature(test)] - -mod frecency; -mod fuzzy; - -pub mod extern_ffi { - use crate::frecency::FrecencyTracker; - use crate::fuzzy::{self, FuzzyOptions, LspItem}; - use lazy_static::lazy_static; - use regex::Regex; - use std::collections::HashSet; - use std::sync::RwLock; - - lazy_static! { - static ref REGEX: Regex = Regex::new(r"[A-Za-z][A-Za-z0-9_\\-]{2,32}").unwrap(); - static ref FRECENCY: RwLock> = RwLock::new(None); - } - - pub fn init_db(db_path: String) -> bool { - let mut frecency = FRECENCY.write().unwrap(); - if frecency.is_some() { - return false; - } - *frecency = Some(FrecencyTracker::new(&db_path)); - true - } - - pub fn destroy_db() -> bool { - // todo: there should be a way to get rid of old locks - // since a crash would result in a leak - let frecency = FRECENCY.write().unwrap(); - drop(frecency); - - let mut frecency = FRECENCY.write().unwrap(); - *frecency = None; - true - } - - pub fn access(item: LspItem) -> bool { - let mut frecency_handle = FRECENCY.write().unwrap(); - let frecency = frecency_handle.as_mut().unwrap(); - frecency.access(&item).unwrap(); - true - } - - pub fn fuzzy( - needle: String, - haystack_labels: Vec, - haystack_kinds: Vec, - haystack_score_offsets: Vec, - haystack_sources: Vec, - opts: FuzzyOptions, - ) -> Vec { - let mut frecency_handle = FRECENCY.write().unwrap(); - let frecency = frecency_handle.as_mut().unwrap(); - - let haystack = (0..haystack_labels.len()) - .map(|i| LspItem { - label: haystack_labels[i].clone(), - sort_text: None, - filter_text: None, - kind: haystack_kinds[i], - score_offset: Some(haystack_score_offsets[i]), - source: haystack_sources[i].clone(), - }) - .collect::>(); - fuzzy::fuzzy(needle, haystack, frecency, opts) - .into_iter() - .map(|i| i as u32) - .collect() - } - - pub fn get_words(text: String) -> Vec { - REGEX - .find_iter(&text) - .map(|m| m.as_str().to_string()) - .collect::>() - .into_iter() - .collect() - } -} - -include!(concat!(env!("OUT_DIR"), "/ffi.rs")); diff --git a/lua/blink/cmp/fuzzy/init.lua b/lua/blink/cmp/fuzzy/init.lua index ae3d124a4..46198d866 100644 --- a/lua/blink/cmp/fuzzy/init.lua +++ b/lua/blink/cmp/fuzzy/init.lua @@ -5,7 +5,7 @@ local fuzzy = { last_context = nil, ---@type blink.cmp.CompletionItem[]? last_items = nil, - rust = require('blink.cmp.fuzzy.ffi'), + rust = require('libblink_cmp_fuzzy'), } ---@param db_path string diff --git a/lua/blink/cmp/init.lua b/lua/blink/cmp/init.lua index b45e0b10a..25ebae095 100644 --- a/lua/blink/cmp/init.lua +++ b/lua/blink/cmp/init.lua @@ -5,67 +5,60 @@ cmp.setup = function(opts) local config = require('blink.cmp.config') config.merge_with(opts) - require('blink.cmp.fuzzy.download').ensure_downloaded(function(err) - if err then - vim.notify('Error while downloading blink.cmp pre-built binary: ' .. err, vim.log.levels.ERROR) - return + cmp.add_default_highlights() + + require('blink.cmp.keymap').setup(config.keymap) + + -- STRUCTURE + -- trigger -> sources -> fuzzy (filter/sort) -> windows (render) + + -- trigger controls when to show the window and the current context for caching + -- TODO: add first_trigger event for setting up the rest of the plugin + cmp.trigger = require('blink.cmp.trigger.completion').activate_autocmds() + + -- sources fetch autocomplete items, documentation and signature help + cmp.sources = require('blink.cmp.sources.lib') + cmp.sources.register() + + -- windows render and apply completion items and signature help + cmp.windows = { + autocomplete = require('blink.cmp.windows.autocomplete').setup(), + documentation = require('blink.cmp.windows.documentation').setup(), + } + + -- fuzzy combines smith waterman with frecency + -- and bonus from proximity words but I'm still working + -- on tuning the weights + --- @param context blink.cmp.Context + --- @param items blink.cmp.CompletionItem[] | nil + local function update_completions(context, items) + if not cmp.fuzzy then + cmp.fuzzy = require('blink.cmp.fuzzy') + cmp.fuzzy.init_db(vim.fn.stdpath('data') .. '/blink/cmp/fuzzy.db') end - - cmp.add_default_highlights() - - require('blink.cmp.keymap').setup(config.keymap) - - -- STRUCTURE - -- trigger -> sources -> fuzzy (filter/sort) -> windows (render) - - -- trigger controls when to show the window and the current context for caching - -- TODO: add first_trigger event for setting up the rest of the plugin - cmp.trigger = require('blink.cmp.trigger.completion').activate_autocmds() - - -- sources fetch autocomplete items, documentation and signature help - cmp.sources = require('blink.cmp.sources.lib') - cmp.sources.register() - - -- windows render and apply completion items and signature help - cmp.windows = { - autocomplete = require('blink.cmp.windows.autocomplete').setup(), - documentation = require('blink.cmp.windows.documentation').setup(), - } - - -- fuzzy combines smith waterman with frecency - -- and bonus from proximity words but I'm still working - -- on tuning the weights - --- @param context blink.cmp.Context - --- @param items blink.cmp.CompletionItem[] | nil - local function update_completions(context, items) - if not cmp.fuzzy then - cmp.fuzzy = require('blink.cmp.fuzzy') - cmp.fuzzy.init_db(vim.fn.stdpath('data') .. '/blink/cmp/fuzzy.db') + -- we avoid adding 1-4ms to insertion latency by scheduling for later + vim.schedule(function() + local filtered_items = cmp.fuzzy.filter_items_with_cache(cmp.fuzzy.get_query(), context, items) + if #filtered_items > 0 then + cmp.windows.autocomplete.open_with_items(context, filtered_items) + else + cmp.windows.autocomplete.close() end - -- we avoid adding 1-4ms to insertion latency by scheduling for later - vim.schedule(function() - local filtered_items = cmp.fuzzy.filter_items_with_cache(cmp.fuzzy.get_query(), context, items) - if #filtered_items > 0 then - cmp.windows.autocomplete.open_with_items(context, filtered_items) - else - cmp.windows.autocomplete.close() - end - end) - end - - cmp.trigger.listen_on_show(function(context) - update_completions(context) -- immediately update via cache on keystroke - cmp.sources.request_completions(context) - end) - cmp.trigger.listen_on_hide(function() - cmp.sources.cancel_completions() - cmp.windows.autocomplete.close() end) - cmp.sources.listen_on_completions(update_completions) + end - -- setup signature help if enabled - if config.trigger.signature_help.enabled then cmp.setup_signature_help() end + cmp.trigger.listen_on_show(function(context) + update_completions(context) -- immediately update via cache on keystroke + cmp.sources.request_completions(context) + end) + cmp.trigger.listen_on_hide(function() + cmp.sources.cancel_completions() + cmp.windows.autocomplete.close() end) + cmp.sources.listen_on_completions(update_completions) + + -- setup signature help if enabled + if config.trigger.signature_help.enabled then cmp.setup_signature_help() end end cmp.setup_signature_help = function() diff --git a/lua/blink/cmp/sources/buffer.lua b/lua/blink/cmp/sources/buffer.lua index 584d51d49..3330de7f7 100644 --- a/lua/blink/cmp/sources/buffer.lua +++ b/lua/blink/cmp/sources/buffer.lua @@ -53,7 +53,7 @@ local function run_sync(buf_text, callback) callback(words_to_items(require('bli local function run_async(buf_text, callback) local worker = uv.new_work( -- must use ffi directly since the normal one requires the config which isnt present - function(items) return table.concat(require('blink.cmp.fuzzy.ffi').get_words(items), '\n') end, + function(items) return table.concat(require('libblink_cmp_fuzzy').get_words(items), '\n') end, function(words) local items = words_to_items(vim.split(words, '\n')) vim.schedule(function() callback(items) end) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 5d56faf9a..cd9725832 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,3 @@ [toolchain] channel = "nightly" +components = [ "rustfmt", "rustc-dev", "rust-analyzer" ] diff --git a/share/lua/5.2/luarocks/build/rust-mlua.lua b/share/lua/5.2/luarocks/build/rust-mlua.lua new file mode 100644 index 000000000..16be0261d --- /dev/null +++ b/share/lua/5.2/luarocks/build/rust-mlua.lua @@ -0,0 +1,92 @@ +local fs = require("luarocks.fs") +local cfg = require("luarocks.core.cfg") +local dir = require("luarocks.dir") +local path = require("luarocks.path") +local util = require("luarocks.util") + +local mlua = {} + +function mlua.run(rockspec, no_install) + assert(rockspec:type() == "rockspec") + + if not fs.is_tool_available("cargo", "Cargo") then + return nil, "'cargo' is not installed.\n" .. "This rock is written in Rust: make sure you have a Rust\n" .. + "development environment installed and try again." + end + + local features = {} + local lua_version = cfg.lua_version + + -- Activate features depending on Lua version + if lua_version == "5.4" then + table.insert(features, "lua54") + elseif lua_version == "5.3" then + table.insert(features, "lua53") + elseif lua_version == "5.2" then + table.insert(features, "lua52") + elseif lua_version == "5.1" then + -- cfg.luajit_version exists in 3.1.x but not 3.9.x + if (util.get_luajit_version and util.get_luajit_version() ~= nil) or cfg.luajit_version then + table.insert(features, "luajit") + else + table.insert(features, "lua51") + end + else + return nil, "Lua version " .. lua_version .. " is not supported" + end + + local cmd = {"cargo build --release"} + + local target_path = rockspec.build and rockspec.build.target_path or "target" + table.insert(cmd, "--target-dir=" .. fs.Q(target_path)) + + if rockspec.build then + -- Check if default features not required + if rockspec.build.default_features == false then + table.insert(cmd, "--no-default-features") + end + -- Add additional features + if type(rockspec.build.features) == "table" then + for _, feature in ipairs(rockspec.build.features) do + table.insert(features, feature) + end + elseif type(rockspec.build.features) == "string" then + table.insert(features, rockspec.build.features) + end + end + table.insert(cmd, "--features") + table.insert(cmd, table.concat(features, ",")) + + if not fs.execute(table.concat(cmd, " ")) then + return nil, "Failed building." + end + + if rockspec.build and rockspec.build.modules and not (no_install) then + local libdir = path.lib_dir(rockspec.name, rockspec.version) + + fs.make_dir(dir.dir_name(libdir)) + for mod, rustlib_name in pairs(rockspec.build.modules) do + -- If `mod` is a number, then it's an array entry + if type(mod) == "number" then + mod = rustlib_name + end + + local rustlib = "lib" .. rustlib_name .. "." .. cfg.external_lib_extension + if cfg.is_platform("windows") then + rustlib = mod .. "." .. cfg.external_lib_extension + end + + local src = dir.path(target_path, "release", rustlib) + local dst = dir.path(libdir, mod .. "." .. cfg.lib_extension) + + local ok, err = fs.copy(src, dst, "exec") + if not ok then + return nil, "Failed installing " .. src .. " in " .. dst .. ": " .. err + end + end + end + + return true +end + +return mlua diff --git a/lua/blink/cmp/fuzzy/frecency.rs b/src/frecency.rs similarity index 99% rename from lua/blink/cmp/fuzzy/frecency.rs rename to src/frecency.rs index 1c93c38ee..457b39613 100644 --- a/lua/blink/cmp/fuzzy/frecency.rs +++ b/src/frecency.rs @@ -22,6 +22,7 @@ impl From<&LspItem> for CompletionItemKey { } } +#[derive(Debug)] pub struct FrecencyTracker { env: Env, db: Database, SerdeBincode>>, diff --git a/lua/blink/cmp/fuzzy/fuzzy.rs b/src/fuzzy.rs similarity index 62% rename from lua/blink/cmp/fuzzy/fuzzy.rs rename to src/fuzzy.rs index d72a0b318..6491a95a5 100644 --- a/lua/blink/cmp/fuzzy/fuzzy.rs +++ b/src/fuzzy.rs @@ -1,12 +1,14 @@ // TODO: refactor this heresy use crate::frecency::FrecencyTracker; -use lua_marshalling::LuaMarshalling; +use mlua::prelude::*; +use mlua::FromLua; +use mlua::Lua; use serde::{Deserialize, Serialize}; use std::cmp::Reverse; use std::collections::HashSet; -#[derive(Clone, Serialize, Deserialize, LuaMarshalling)] +#[derive(Clone, Serialize, Deserialize, Debug)] pub struct LspItem { pub label: String, #[serde(rename = "sortText")] @@ -18,7 +20,31 @@ pub struct LspItem { pub source: String, } -#[derive(Clone, LuaMarshalling)] +impl FromLua<'_> for LspItem { + fn from_lua(value: LuaValue<'_>, _lua: &'_ Lua) -> LuaResult { + if let Some(tab) = value.as_table() { + let label: String = tab.get("label").unwrap_or_default(); + let sort_text: Option = tab.get("sortText").ok(); + let filter_text: Option = tab.get("filterText").ok(); + let kind: u32 = tab.get("kind").unwrap_or_default(); + let score_offset: Option = tab.get("score_offset").ok(); + let source: String = tab.get("source").unwrap_or_default(); + + Ok(LspItem { + label, + sort_text, + filter_text, + kind, + score_offset, + source, + }) + } else { + Err(mlua::Error::FromLuaConversionError { from: "LuaValue" , to: "LspItem", message: None }) + } + } +} + +#[derive(Clone, Serialize, Deserialize)] pub struct MatchedLspItem { label: String, kind: u32, @@ -26,15 +52,37 @@ pub struct MatchedLspItem { score: i32, } -#[derive(LuaMarshalling)] +#[derive(Clone, Serialize, Deserialize, Hash)] pub struct FuzzyOptions { use_frecency: bool, nearby_words: Option>, min_score: u16, - max_items: usize, + max_items: u32, sorts: Vec, } +impl FromLua<'_> for FuzzyOptions { + fn from_lua(value: LuaValue<'_>, _lua: &'_ Lua) -> LuaResult { + if let Some(tab) = value.as_table() { + let use_frecency: bool = tab.get("use_frecency").unwrap_or_default(); + let nearby_words: Option> = tab.get("nearby_words").ok(); + let min_score: u16 = tab.get("min_score").unwrap_or_default(); + let max_items: u32 = tab.get("max_items").unwrap_or_default(); + let sorts: Vec = tab.get("sorts").unwrap_or_default(); + + Ok(FuzzyOptions { + use_frecency, + nearby_words, + min_score, + max_items, + sorts, + }) + } else { + Err(mlua::Error::FromLuaConversionError { from: "LuaValue", to: "FuzzyOptions", message: None }) + } + } +} + pub fn fuzzy( needle: String, haystack: Vec, @@ -108,6 +156,6 @@ pub fn fuzzy( matches .iter() .map(|mtch| mtch.index_in_haystack) - .take(opts.max_items) + .take(opts.max_items as usize) .collect::>() } diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 000000000..3509e4aa3 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,91 @@ +use crate::frecency::FrecencyTracker; +use crate::fuzzy::{FuzzyOptions, LspItem}; +use lazy_static::lazy_static; +use mlua::prelude::*; +use regex::Regex; +use std::collections::HashSet; +use std::sync::RwLock; + +mod frecency; +mod fuzzy; + +lazy_static! { + static ref REGEX: Regex = Regex::new(r"[A-Za-z][A-Za-z0-9_\\-]{2,32}").unwrap(); + static ref FRECENCY: RwLock> = RwLock::new(None); +} + +pub fn init_db(_: &Lua, db_path: String) -> LuaResult { + let mut frecency = FRECENCY.write().unwrap(); + if frecency.is_some() { + return Ok(false); + } + *frecency = Some(FrecencyTracker::new(&db_path)); + Ok(true) +} + +pub fn destroy_db(_: &Lua, _: ()) -> LuaResult { + // todo: there should be a way to get rid of old locks + // since a crash would result in a leak + let frecency = FRECENCY.write().unwrap(); + drop(frecency); + let mut frecency = FRECENCY.write().unwrap(); + *frecency = None; + Ok(true) +} + +pub fn access(_: &Lua, item: LspItem) -> LuaResult { + let mut frecency_handle = FRECENCY.write().unwrap(); + let frecency = frecency_handle.as_mut().unwrap(); + frecency.access(&item)?; + Ok(true) +} + +// pretty confident this is the entry point +pub fn fuzzy( + _lua: &Lua, + (needle, haystack_labels, haystack_kinds, haystack_score_offsets, haystack_sources, opts): ( + String, + Vec, + Vec, + Vec, + Vec, + FuzzyOptions, // so this is the problem + ), +) -> LuaResult> { + let mut frecency_handle = FRECENCY.write().unwrap(); + let frecency = frecency_handle.as_mut().unwrap(); + let haystack = (0..haystack_labels.len()) + .map(|i| LspItem { + label: haystack_labels[i].clone(), + sort_text: None, + filter_text: None, + kind: haystack_kinds[i], + score_offset: Some(haystack_score_offsets[i]), + source: haystack_sources[i].clone(), + }) + .collect::>(); + Ok(fuzzy::fuzzy(needle, haystack, frecency, opts) + .into_iter() + .map(|i| i as u32) + .collect()) +} + +pub fn get_words(_: &Lua, text: String) -> LuaResult> { + Ok(REGEX + .find_iter(&text) + .map(|m| m.as_str().to_string()) + .collect::>() + .into_iter() + .collect()) +} + +#[mlua::lua_module] +fn libblink_cmp_fuzzy(lua: &Lua) -> LuaResult { + let exports = lua.create_table()?; + exports.set("fuzzy", lua.create_function(fuzzy)?)?; + exports.set("get_words", lua.create_function(get_words)?)?; + exports.set("init_db", lua.create_function(init_db)?)?; + exports.set("destroy_db", lua.create_function(destroy_db)?)?; + exports.set("access", lua.create_function(access)?)?; + Ok(exports) +} From b0cbf037d02f8d5f37b55f6d323ca0e02ed66fa7 Mon Sep 17 00:00:00 2001 From: Liam Dyer Date: Fri, 18 Oct 2024 10:41:12 -0400 Subject: [PATCH 02/11] feat: drop rockspec, deserialize in rust --- Cargo.toml | 7 +- blink-cmp-scm-1.rockspec | 44 --------- {src => fuzzy}/frecency.rs | 0 {src => fuzzy}/fuzzy.rs | 0 {src => fuzzy}/lib.rs | 23 +---- .../0.2.2-1/doc/CHANGELOG.md | 17 ---- .../0.2.2-1/doc/LICENSE | 21 ----- .../0.2.2-1/doc/README.md | 50 ---------- .../luarocks-build-rust-mlua-0.2.2-1.rockspec | 14 --- .../0.2.2-1/rock_manifest | 15 --- lib/luarocks/rocks-5.2/manifest | 25 ----- libblink_cmp_fuzzy.so | 1 - lua/blink/cmp/fuzzy/init.lua | 42 +++------ lua/libblink_cmp_fuzzy.so | 1 + share/lua/5.2/luarocks/build/rust-mlua.lua | 92 ------------------- 15 files changed, 20 insertions(+), 332 deletions(-) delete mode 100644 blink-cmp-scm-1.rockspec rename {src => fuzzy}/frecency.rs (100%) rename {src => fuzzy}/fuzzy.rs (100%) rename {src => fuzzy}/lib.rs (75%) delete mode 100644 lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/CHANGELOG.md delete mode 100644 lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/LICENSE delete mode 100644 lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/README.md delete mode 100644 lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/luarocks-build-rust-mlua-0.2.2-1.rockspec delete mode 100644 lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/rock_manifest delete mode 100644 lib/luarocks/rocks-5.2/manifest delete mode 120000 libblink_cmp_fuzzy.so create mode 120000 lua/libblink_cmp_fuzzy.so delete mode 100644 share/lua/5.2/luarocks/build/rust-mlua.lua diff --git a/Cargo.toml b/Cargo.toml index 91f0bdcef..9827df4d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,16 +4,13 @@ version = "0.1.0" edition = "2021" [lib] +path = "fuzzy/lib.rs" crate-type = ["cdylib"] -[features] -luajit = ["mlua/luajit"] -lua51 = ["mlua/lua51"] - [dependencies] regex = "1.10.5" lazy_static = "1.5.0" frizbee = { git = "https://github.com/saghen/frizbee" } serde = { version = "1.0.204", features = ["derive"] } heed = "0.20.3" -mlua = { version = "0.9.9", features = ["module"] } +mlua = { version = "0.9.9", features = ["module", "luajit"] } diff --git a/blink-cmp-scm-1.rockspec b/blink-cmp-scm-1.rockspec deleted file mode 100644 index cf2fd1bb9..000000000 --- a/blink-cmp-scm-1.rockspec +++ /dev/null @@ -1,44 +0,0 @@ -local MODREV, SPECREV = "scm", "-1" -rockspec_format = "3.0" -package = "blink-cmp" -version = MODREV .. SPECREV - -description = { - summary = "Performant, batteries-included completion plugin for Neovim", - labels = { "neovim" }, - homepage = "https://github.com/Saghen/blink.cmp", - license = "MIT", -} - -source = { - url = "http://github.com/Saghen/blink-cmp/archive/v" .. MODREV .. ".zip", -} - -if MODREV == "scm" then - source = { - url = "git://github.com/Saghen/blink-cmp", - } -end - -dependencies = { - "lua = 5.1", -} - -build_dependencies = { - "luarocks-build-rust-mlua", -} - -build = { - type = "rust-mlua", - - modules = { - ["libblink_cmp_fuzzy"] = "blink_cmp_fuzzy", - }, - - install = { - lua = { - ["blink-cmp.init"] = "lua/blink-cmp.lua", - }, - }, - features = { "lua51" } -} diff --git a/src/frecency.rs b/fuzzy/frecency.rs similarity index 100% rename from src/frecency.rs rename to fuzzy/frecency.rs diff --git a/src/fuzzy.rs b/fuzzy/fuzzy.rs similarity index 100% rename from src/fuzzy.rs rename to fuzzy/fuzzy.rs diff --git a/src/lib.rs b/fuzzy/lib.rs similarity index 75% rename from src/lib.rs rename to fuzzy/lib.rs index 3509e4aa3..fe1bf5822 100644 --- a/src/lib.rs +++ b/fuzzy/lib.rs @@ -36,34 +36,17 @@ pub fn destroy_db(_: &Lua, _: ()) -> LuaResult { pub fn access(_: &Lua, item: LspItem) -> LuaResult { let mut frecency_handle = FRECENCY.write().unwrap(); let frecency = frecency_handle.as_mut().unwrap(); - frecency.access(&item)?; + frecency.access(&item).unwrap(); Ok(true) } -// pretty confident this is the entry point pub fn fuzzy( _lua: &Lua, - (needle, haystack_labels, haystack_kinds, haystack_score_offsets, haystack_sources, opts): ( - String, - Vec, - Vec, - Vec, - Vec, - FuzzyOptions, // so this is the problem - ), + (needle, haystack, opts): (String, Vec, FuzzyOptions), ) -> LuaResult> { let mut frecency_handle = FRECENCY.write().unwrap(); let frecency = frecency_handle.as_mut().unwrap(); - let haystack = (0..haystack_labels.len()) - .map(|i| LspItem { - label: haystack_labels[i].clone(), - sort_text: None, - filter_text: None, - kind: haystack_kinds[i], - score_offset: Some(haystack_score_offsets[i]), - source: haystack_sources[i].clone(), - }) - .collect::>(); + Ok(fuzzy::fuzzy(needle, haystack, frecency, opts) .into_iter() .map(|i| i as u32) diff --git a/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/CHANGELOG.md b/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/CHANGELOG.md deleted file mode 100644 index 38ef9a873..000000000 --- a/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/CHANGELOG.md +++ /dev/null @@ -1,17 +0,0 @@ -## v0.2.2 - -- Pass correct `target-dir` arg to cargo instead of `target` (mlua-rs/luarocks-build-rust-mlua#12) - -## v0.2.1 (yanked) - -- Pass `target_path` to cargo if it's set (mlua-rs/luarocks-build-rust-mlua#9) -- Re-enable support for LuaRocks 3.1.x (mlua-rs/luarocks-build-rust-mlua#10) - -## v0.2.0 - -This release lines up with the mlua v0.9 changes - -- Do not require lua headers or lib on Windows (modules are linked with `lua5x.dll`) -- Never pass `vendored` feature (makes no sense in the module mode) -- Support `default_features = false` option to pass `--no-default-features` to cargo -- Support `features` option to pass additional features to cargo diff --git a/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/LICENSE b/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/LICENSE deleted file mode 100644 index a78c81b36..000000000 --- a/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2021 A. Orlenko - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/README.md b/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/README.md deleted file mode 100644 index f6c87a992..000000000 --- a/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/doc/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# luarocks-build-rust-mlua - -A [LuaRocks] build backend for Lua modules written in Rust using [mlua]. - -[LuaRocks]: http://luarocks.org -[mlua]: http://github.com/mlua-rs/mlua - -# Example rockspec - -```lua -package = "my_module" -version = "0.1.0-1" - -source = { - url = "git+https://github.com/username/my_module", - tag = "0.1.0", -} - -description = { - summary = "Example Lua module in Rust", - detailed = "...", - homepage = "https://github.com/username/my_module", - license = "MIT" -} - -dependencies = { - "lua >= 5.1", - "luarocks-build-rust-mlua", -} - -build = { - type = "rust-mlua", - - modules = { - -- Native library expected in `/release/libmy_module.so` (linux; uses right name on macos/windows) - "my_module", - -- More complex case, native library expected in `/release/libalt_name.so` - ["my_module"] = "alt_name", - }, - - -- Optional: target_path if cargo "target" directory not in the module root - target_path = "path/to/cargo/target/directory" - - -- Optional: if set to `false` pass `--no-default-features` to cargo - default_features = false, - - -- Optional: pass additional features - features = {"extra", "features"} -} -``` diff --git a/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/luarocks-build-rust-mlua-0.2.2-1.rockspec b/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/luarocks-build-rust-mlua-0.2.2-1.rockspec deleted file mode 100644 index 76a4a4bff..000000000 --- a/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/luarocks-build-rust-mlua-0.2.2-1.rockspec +++ /dev/null @@ -1,14 +0,0 @@ -rockspec_format = "3.0" -package = "luarocks-build-rust-mlua" -version = "0.2.2-1" - -source = { - url = "git+https://github.com/mlua-rs/luarocks-build-rust-mlua", - tag = "0.2.2", -} - -description = { - summary = "A LuaRocks build backend for Lua modules written in Rust using mlua", - homepage = "https://github.com/mlua-rs/luarocks-build-rust-mlua", - license = "MIT", -} diff --git a/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/rock_manifest b/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/rock_manifest deleted file mode 100644 index 777fd1fdb..000000000 --- a/lib/luarocks/rocks-5.2/luarocks-build-rust-mlua/0.2.2-1/rock_manifest +++ /dev/null @@ -1,15 +0,0 @@ -rock_manifest = { - doc = { - ["CHANGELOG.md"] = "319bd4edc94b46360328e3693edc2448", - LICENSE = "31a0963ca1b66065691cc341103d1e50", - ["README.md"] = "2261bffc33134e7e2f5776ad9e8691a4" - }, - lua = { - luarocks = { - build = { - ["rust-mlua.lua"] = "c0347aec6cfa2cb849f789a10f9281a1" - } - } - }, - ["luarocks-build-rust-mlua-0.2.2-1.rockspec"] = "976b0a28ea6d00733f449c764528bdda" -} diff --git a/lib/luarocks/rocks-5.2/manifest b/lib/luarocks/rocks-5.2/manifest deleted file mode 100644 index 8a20c3227..000000000 --- a/lib/luarocks/rocks-5.2/manifest +++ /dev/null @@ -1,25 +0,0 @@ -commands = {} -dependencies = { - ["luarocks-build-rust-mlua"] = { - ["0.2.2-1"] = {} - } -} -modules = { - ["luarocks.build.rust-mlua"] = { - "luarocks-build-rust-mlua/0.2.2-1" - } -} -repository = { - ["luarocks-build-rust-mlua"] = { - ["0.2.2-1"] = { - { - arch = "installed", - commands = {}, - dependencies = {}, - modules = { - ["luarocks.build.rust-mlua"] = "luarocks/build/rust-mlua.lua" - } - } - } - } -} diff --git a/libblink_cmp_fuzzy.so b/libblink_cmp_fuzzy.so deleted file mode 120000 index b7f0e2433..000000000 --- a/libblink_cmp_fuzzy.so +++ /dev/null @@ -1 +0,0 @@ -./target/release/libblink_cmp_fuzzy.so \ No newline at end of file diff --git a/lua/blink/cmp/fuzzy/init.lua b/lua/blink/cmp/fuzzy/init.lua index 46198d866..e4ec428f2 100644 --- a/lua/blink/cmp/fuzzy/init.lua +++ b/lua/blink/cmp/fuzzy/init.lua @@ -28,21 +28,8 @@ function fuzzy.get_words(lines) return fuzzy.rust.get_words(lines) end ---@param needle string ---@param items blink.cmp.CompletionItem[]? ---@return blink.cmp.CompletionItem[] -function fuzzy.filter_items(needle, items) - -- convert to table of strings - local haystack_labels = {} - local haystack_score_offsets = {} - local haystack_kinds = {} - local haystack_sources = {} - - items = items or {} - - for _, item in ipairs(items) do - table.insert(haystack_labels, item.label) - table.insert(haystack_score_offsets, item.score_offset or 0) - table.insert(haystack_kinds, item.kind) - table.insert(haystack_sources, item.source) - end +function fuzzy.filter_items(needle, haystack) + haystack = haystack or {} -- get the nearby words local cursor_row = vim.api.nvim_win_get_cursor(0)[1] @@ -53,21 +40,20 @@ function fuzzy.filter_items(needle, items) -- perform fuzzy search local filtered_items = {} - local matched_indices = - fuzzy.rust.fuzzy(needle, haystack_labels, haystack_kinds, haystack_score_offsets, haystack_sources, { - -- each matching char is worth 4 points and it receives a bonus for capitalization, delimiter and prefix - -- so this should generally be good - -- TODO: make this configurable - min_score = 6 * needle:len(), - max_items = config.max_items, - use_frecency = config.use_frecency, - use_proximity = config.use_proximity, - sorts = config.sorts, - nearby_words = nearby_words, - }) + local matched_indices = fuzzy.rust.fuzzy(needle, haystack, { + -- each matching char is worth 4 points and it receives a bonus for capitalization, delimiter and prefix + -- so this should generally be good + -- TODO: make this configurable + min_score = 6 * needle:len(), + max_items = config.max_items, + use_frecency = config.use_frecency, + use_proximity = config.use_proximity, + sorts = config.sorts, + nearby_words = nearby_words, + }) for _, idx in ipairs(matched_indices) do - table.insert(filtered_items, items[idx + 1]) + table.insert(filtered_items, haystack[idx + 1]) end return filtered_items diff --git a/lua/libblink_cmp_fuzzy.so b/lua/libblink_cmp_fuzzy.so new file mode 120000 index 000000000..37fb296db --- /dev/null +++ b/lua/libblink_cmp_fuzzy.so @@ -0,0 +1 @@ +../target/release/libblink_cmp_fuzzy.so \ No newline at end of file diff --git a/share/lua/5.2/luarocks/build/rust-mlua.lua b/share/lua/5.2/luarocks/build/rust-mlua.lua deleted file mode 100644 index 16be0261d..000000000 --- a/share/lua/5.2/luarocks/build/rust-mlua.lua +++ /dev/null @@ -1,92 +0,0 @@ -local fs = require("luarocks.fs") -local cfg = require("luarocks.core.cfg") -local dir = require("luarocks.dir") -local path = require("luarocks.path") -local util = require("luarocks.util") - -local mlua = {} - -function mlua.run(rockspec, no_install) - assert(rockspec:type() == "rockspec") - - if not fs.is_tool_available("cargo", "Cargo") then - return nil, "'cargo' is not installed.\n" .. "This rock is written in Rust: make sure you have a Rust\n" .. - "development environment installed and try again." - end - - local features = {} - local lua_version = cfg.lua_version - - -- Activate features depending on Lua version - if lua_version == "5.4" then - table.insert(features, "lua54") - elseif lua_version == "5.3" then - table.insert(features, "lua53") - elseif lua_version == "5.2" then - table.insert(features, "lua52") - elseif lua_version == "5.1" then - -- cfg.luajit_version exists in 3.1.x but not 3.9.x - if (util.get_luajit_version and util.get_luajit_version() ~= nil) or cfg.luajit_version then - table.insert(features, "luajit") - else - table.insert(features, "lua51") - end - else - return nil, "Lua version " .. lua_version .. " is not supported" - end - - local cmd = {"cargo build --release"} - - local target_path = rockspec.build and rockspec.build.target_path or "target" - table.insert(cmd, "--target-dir=" .. fs.Q(target_path)) - - if rockspec.build then - -- Check if default features not required - if rockspec.build.default_features == false then - table.insert(cmd, "--no-default-features") - end - -- Add additional features - if type(rockspec.build.features) == "table" then - for _, feature in ipairs(rockspec.build.features) do - table.insert(features, feature) - end - elseif type(rockspec.build.features) == "string" then - table.insert(features, rockspec.build.features) - end - end - table.insert(cmd, "--features") - table.insert(cmd, table.concat(features, ",")) - - if not fs.execute(table.concat(cmd, " ")) then - return nil, "Failed building." - end - - if rockspec.build and rockspec.build.modules and not (no_install) then - local libdir = path.lib_dir(rockspec.name, rockspec.version) - - fs.make_dir(dir.dir_name(libdir)) - for mod, rustlib_name in pairs(rockspec.build.modules) do - -- If `mod` is a number, then it's an array entry - if type(mod) == "number" then - mod = rustlib_name - end - - local rustlib = "lib" .. rustlib_name .. "." .. cfg.external_lib_extension - if cfg.is_platform("windows") then - rustlib = mod .. "." .. cfg.external_lib_extension - end - - local src = dir.path(target_path, "release", rustlib) - local dst = dir.path(libdir, mod .. "." .. cfg.lib_extension) - - local ok, err = fs.copy(src, dst, "exec") - if not ok then - return nil, "Failed installing " .. src .. " in " .. dst .. ": " .. err - end - end - end - - return true -end - -return mlua From 4a2fe281a3d369ca1143bb1d595864628d40112c Mon Sep 17 00:00:00 2001 From: Liam Dyer Date: Fri, 18 Oct 2024 10:48:08 -0400 Subject: [PATCH 03/11] feat: restore release workflow --- .cargo/config.toml | 6 ++ .github/workflows/luarocks.yaml | 31 --------- .github/workflows/release-please.yaml | 22 ------- .github/workflows/release.yaml | 92 +++++++++++++++++++++++++++ .github/workflows/template.rockspec | 52 --------------- README.md | 2 - 6 files changed, 98 insertions(+), 107 deletions(-) delete mode 100644 .github/workflows/luarocks.yaml delete mode 100644 .github/workflows/release-please.yaml create mode 100644 .github/workflows/release.yaml delete mode 100644 .github/workflows/template.rockspec diff --git a/.cargo/config.toml b/.cargo/config.toml index d47f983e4..ed561c712 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -9,3 +9,9 @@ rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] + +[target.x86_64-unknown-linux-musl] +rustflags = ["-C", "target-feature=-crt-static"] + +[target.aarch64-unknown-linux-musl] +rustflags = ["-C", "target-feature=-crt-static"] diff --git a/.github/workflows/luarocks.yaml b/.github/workflows/luarocks.yaml deleted file mode 100644 index 4bb52ea3a..000000000 --- a/.github/workflows/luarocks.yaml +++ /dev/null @@ -1,31 +0,0 @@ - -name: Push to Luarocks - -on: - push: - tags: - - '*' - release: - types: - - created - pull_request: # Test luarocks install without publishing on PR - workflow_dispatch: - -jobs: - luarocks-upload: - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 # Required to count the commits - - name: Get Version - run: echo "LUAROCKS_VERSION=$(git describe --abbrev=0 --tags)" >> $GITHUB_ENV - - name: LuaRocks Upload - uses: nvim-neorocks/luarocks-tag-release@v6 - env: - LUAROCKS_API_KEY: ${{ secrets.LUAROCKS_API_KEY }} - with: - version: ${{ env.LUAROCKS_VERSION }} - template: "./.github/workflows/template.rockspec" - dependencies: | - lua ~> 5.1 diff --git a/.github/workflows/release-please.yaml b/.github/workflows/release-please.yaml deleted file mode 100644 index 84321dbbe..000000000 --- a/.github/workflows/release-please.yaml +++ /dev/null @@ -1,22 +0,0 @@ ---- -permissions: - contents: write - pull-requests: write - -name: Release Please - -on: - workflow_dispatch: - push: - branches: - - main - -jobs: - release: - name: release - runs-on: ubuntu-latest - steps: - - uses: google-github-actions/release-please-action@v4 - with: - release-type: simple - token: ${{ secrets.PAT }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 000000000..06f108ee9 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,92 @@ +name: Release + +on: + push: + tags: + - "v*" + +jobs: + build: + name: Build ${{ matrix.target }} + runs-on: ${{ matrix.os }} + permissions: + contents: read + strategy: + matrix: + include: + # Linux builds (statically linked for compatibility, have to use glibc for FFI) + - os: ubuntu-latest + target: x86_64-unknown-linux-gnu + artifact_name: target/x86_64-unknown-linux-gnu/release/libblink_cmp_fuzzy.so + - os: ubuntu-latest + target: aarch64-unknown-linux-gnu + artifact_name: target/aarch64-unknown-linux-gnu/release/libblink_cmp_fuzzy.so + + # macOS builds + - os: macos-latest + target: x86_64-apple-darwin + artifact_name: target/x86_64-apple-darwin/release/libblink_cmp_fuzzy.dylib + - os: macos-latest + target: aarch64-apple-darwin + artifact_name: target/aarch64-apple-darwin/release/libblink_cmp_fuzzy.dylib + + # Windows builds + - os: windows-latest + target: x86_64-pc-windows-msvc + artifact_name: target/x86_64-pc-windows-msvc/release/blink_cmp_fuzzy.dll + + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + run: | + rustup toolchain install nightly + rustup default nightly + rustup target add ${{ matrix.target }} + + - name: Build for Linux + if: contains(matrix.os, 'ubuntu') + run: | + cargo install cross --git https://github.com/cross-rs/cross + RUSTFLAGS="-C target-feature=-crt-static" cross build --release --target ${{ matrix.target }} + mv "${{ matrix.artifact_name }}" "${{ matrix.target }}.so" + + - name: Build for macOS + if: contains(matrix.os, 'macos') + run: | + # Ventura + MACOSX_DEPLOYMENT_TARGET="13" cargo build --release --target ${{ matrix.target }} + mv "${{ matrix.artifact_name }}" "${{ matrix.target }}.dylib" + + - name: Build for Windows + if: contains(matrix.os, 'windows') + run: | + cargo build --release --target ${{ matrix.target }} + mv "${{ matrix.artifact_name }}" "${{ matrix.target }}.dll" + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.target }} + path: ${{ matrix.target }}.* + + release: + name: Release + needs: build + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Download artifacts + uses: actions/download-artifact@v4 + + - name: Upload Release Assets + uses: softprops/action-gh-release@v2 + with: + name: ${{ github.ref_name }} + tag_name: ${{ github.ref_name }} + token: ${{ github.token }} + files: ./**/* + draft: false + prerelease: false + generate_release_notes: true diff --git a/.github/workflows/template.rockspec b/.github/workflows/template.rockspec deleted file mode 100644 index 20351b3f9..000000000 --- a/.github/workflows/template.rockspec +++ /dev/null @@ -1,52 +0,0 @@ -local git_ref = '$git_ref' -local modrev = '$modrev' -local specrev = '$specrev' - -local repo_url = '$repo_url' - -rockspec_format = '3.0' -package = '$package' -version = modrev ..'-'.. specrev - -description = { - summary = '$summary', - detailed = $detailed_description, - labels = $labels, - homepage = '$homepage', - $license -} - -dependencies = $dependencies - -build_dependencies = { - 'luarocks-build-rust-mlua', -} - -test_dependencies = $test_dependencies - -source = { - url = repo_url .. '/archive/' .. git_ref .. '.zip', - dir = '$repo_name-' .. '$archive_dir_suffix', -} - -if modrev == 'scm' or modrev == 'dev' then - source = { - url = repo_url:gsub('https', 'git') - } -end - -build = { - type = "rust-mlua", - - modules = { - ["libblink_cmp_fuzzy"] = "blink_cmp_fuzzy", - }, - - install = { - lua = { - ["blink-cmp.init"] = "lua/blink-cmp.lua", - }, - }, - - copy_directories = $copy_directories, -} diff --git a/README.md b/README.md index 9d2faf77c..a6f80b97f 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,6 @@ version = 'v0.*', -- OR build from source, requires nightly: https://rust-lang.github.io/rustup/concepts/channels.html#working-with-nightly-rust -- build = 'cargo build --release', - -- On musl libc based systems you need to add this flag - -- build = 'RUSTFLAGS="-C target-feature=-crt-static" cargo build --release', opts = { highlight = { From 530a82cc4d995e5193e6788c84fb67d2adf7b863 Mon Sep 17 00:00:00 2001 From: Liam Dyer Date: Fri, 18 Oct 2024 12:00:31 -0400 Subject: [PATCH 04/11] feat: use blink.cmp.fuzzy.rust for rust module --- fuzzy/lib.rs | 2 +- lua/blink/cmp/fuzzy/init.lua | 2 +- lua/blink/cmp/fuzzy/rust.so | 1 + lua/libblink_cmp_fuzzy.so | 1 - 4 files changed, 3 insertions(+), 3 deletions(-) create mode 120000 lua/blink/cmp/fuzzy/rust.so delete mode 120000 lua/libblink_cmp_fuzzy.so diff --git a/fuzzy/lib.rs b/fuzzy/lib.rs index fe1bf5822..4309e95bc 100644 --- a/fuzzy/lib.rs +++ b/fuzzy/lib.rs @@ -63,7 +63,7 @@ pub fn get_words(_: &Lua, text: String) -> LuaResult> { } #[mlua::lua_module] -fn libblink_cmp_fuzzy(lua: &Lua) -> LuaResult { +fn blink_cmp_fuzzy_rust(lua: &Lua) -> LuaResult { let exports = lua.create_table()?; exports.set("fuzzy", lua.create_function(fuzzy)?)?; exports.set("get_words", lua.create_function(get_words)?)?; diff --git a/lua/blink/cmp/fuzzy/init.lua b/lua/blink/cmp/fuzzy/init.lua index e4ec428f2..02264ceaa 100644 --- a/lua/blink/cmp/fuzzy/init.lua +++ b/lua/blink/cmp/fuzzy/init.lua @@ -5,7 +5,7 @@ local fuzzy = { last_context = nil, ---@type blink.cmp.CompletionItem[]? last_items = nil, - rust = require('libblink_cmp_fuzzy'), + rust = require('blink.cmp.fuzzy.rust'), } ---@param db_path string diff --git a/lua/blink/cmp/fuzzy/rust.so b/lua/blink/cmp/fuzzy/rust.so new file mode 120000 index 000000000..969aa9a59 --- /dev/null +++ b/lua/blink/cmp/fuzzy/rust.so @@ -0,0 +1 @@ +../../../../target/release/libblink_cmp_fuzzy.so \ No newline at end of file diff --git a/lua/libblink_cmp_fuzzy.so b/lua/libblink_cmp_fuzzy.so deleted file mode 120000 index 37fb296db..000000000 --- a/lua/libblink_cmp_fuzzy.so +++ /dev/null @@ -1 +0,0 @@ -../target/release/libblink_cmp_fuzzy.so \ No newline at end of file From d63a14efde25df8e573dabe1075b2738f74ab624 Mon Sep 17 00:00:00 2001 From: Liam Dyer Date: Fri, 18 Oct 2024 14:27:03 -0400 Subject: [PATCH 05/11] feat: support all platforms --- build.rs | 4 ++++ lua/blink/cmp/fuzzy/init.lua | 16 ++++++++++++++-- lua/blink/cmp/fuzzy/{rust.so => rust-linux.so} | 0 lua/blink/cmp/fuzzy/rust-macos.dylib | 1 + lua/blink/cmp/fuzzy/rust-win.dll | 1 + 5 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 build.rs rename lua/blink/cmp/fuzzy/{rust.so => rust-linux.so} (100%) create mode 120000 lua/blink/cmp/fuzzy/rust-macos.dylib create mode 120000 lua/blink/cmp/fuzzy/rust-win.dll diff --git a/build.rs b/build.rs new file mode 100644 index 000000000..380937733 --- /dev/null +++ b/build.rs @@ -0,0 +1,4 @@ +fn main() { + // delete existing version.txt file created by downloader + let _ = std::fs::remove_file("target/release/version.txt"); +} diff --git a/lua/blink/cmp/fuzzy/init.lua b/lua/blink/cmp/fuzzy/init.lua index 02264ceaa..546552759 100644 --- a/lua/blink/cmp/fuzzy/init.lua +++ b/lua/blink/cmp/fuzzy/init.lua @@ -1,11 +1,23 @@ -local config = require('blink.cmp.config').fuzzy +local function load_rust() + local platform = jit.os:lower() + if platform == 'osx' or platform == 'mac' then + return require('blink.cmp.fuzzy.rust-macos') + elseif platform == 'windows' then + return require('blink.cmp.fuzzy.rust-win') + else + return require('blink.cmp.fuzzy.rust-linux') + end +end +---------------- + +local config = require('blink.cmp.config').fuzzy local fuzzy = { ---@type blink.cmp.Context? last_context = nil, ---@type blink.cmp.CompletionItem[]? last_items = nil, - rust = require('blink.cmp.fuzzy.rust'), + rust = load_rust(), } ---@param db_path string diff --git a/lua/blink/cmp/fuzzy/rust.so b/lua/blink/cmp/fuzzy/rust-linux.so similarity index 100% rename from lua/blink/cmp/fuzzy/rust.so rename to lua/blink/cmp/fuzzy/rust-linux.so diff --git a/lua/blink/cmp/fuzzy/rust-macos.dylib b/lua/blink/cmp/fuzzy/rust-macos.dylib new file mode 120000 index 000000000..9ed65aa1a --- /dev/null +++ b/lua/blink/cmp/fuzzy/rust-macos.dylib @@ -0,0 +1 @@ +../../../../target/release/libblink_cmp_fuzzy.dylib \ No newline at end of file diff --git a/lua/blink/cmp/fuzzy/rust-win.dll b/lua/blink/cmp/fuzzy/rust-win.dll new file mode 120000 index 000000000..9fa2797f3 --- /dev/null +++ b/lua/blink/cmp/fuzzy/rust-win.dll @@ -0,0 +1 @@ +../../../../target/release/blink_cmp_fuzzy.dll \ No newline at end of file From cbda28d0d1045b90176dcf09acab282e41af3b16 Mon Sep 17 00:00:00 2001 From: Liam Dyer Date: Fri, 18 Oct 2024 14:35:06 -0400 Subject: [PATCH 06/11] feat: improve multi-platform support --- Cargo.toml | 2 +- {fuzzy => lua/blink/cmp/fuzzy}/frecency.rs | 0 {fuzzy => lua/blink/cmp/fuzzy}/fuzzy.rs | 0 lua/blink/cmp/fuzzy/init.lua | 15 +-------------- {fuzzy => lua/blink/cmp/fuzzy}/lib.rs | 0 lua/blink/cmp/fuzzy/{rust-win.dll => rust.dll} | 0 .../cmp/fuzzy/{rust-macos.dylib => rust.dylib} | 0 lua/blink/cmp/fuzzy/{rust-linux.so => rust.so} | 0 8 files changed, 2 insertions(+), 15 deletions(-) rename {fuzzy => lua/blink/cmp/fuzzy}/frecency.rs (100%) rename {fuzzy => lua/blink/cmp/fuzzy}/fuzzy.rs (100%) rename {fuzzy => lua/blink/cmp/fuzzy}/lib.rs (100%) rename lua/blink/cmp/fuzzy/{rust-win.dll => rust.dll} (100%) rename lua/blink/cmp/fuzzy/{rust-macos.dylib => rust.dylib} (100%) rename lua/blink/cmp/fuzzy/{rust-linux.so => rust.so} (100%) diff --git a/Cargo.toml b/Cargo.toml index 9827df4d1..1ccf2f686 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [lib] -path = "fuzzy/lib.rs" +path = "lua/blink/cmp/fuzzy/lib.rs" crate-type = ["cdylib"] [dependencies] diff --git a/fuzzy/frecency.rs b/lua/blink/cmp/fuzzy/frecency.rs similarity index 100% rename from fuzzy/frecency.rs rename to lua/blink/cmp/fuzzy/frecency.rs diff --git a/fuzzy/fuzzy.rs b/lua/blink/cmp/fuzzy/fuzzy.rs similarity index 100% rename from fuzzy/fuzzy.rs rename to lua/blink/cmp/fuzzy/fuzzy.rs diff --git a/lua/blink/cmp/fuzzy/init.lua b/lua/blink/cmp/fuzzy/init.lua index 546552759..0c97e59c5 100644 --- a/lua/blink/cmp/fuzzy/init.lua +++ b/lua/blink/cmp/fuzzy/init.lua @@ -1,23 +1,10 @@ -local function load_rust() - local platform = jit.os:lower() - if platform == 'osx' or platform == 'mac' then - return require('blink.cmp.fuzzy.rust-macos') - elseif platform == 'windows' then - return require('blink.cmp.fuzzy.rust-win') - else - return require('blink.cmp.fuzzy.rust-linux') - end -end - ----------------- - local config = require('blink.cmp.config').fuzzy local fuzzy = { ---@type blink.cmp.Context? last_context = nil, ---@type blink.cmp.CompletionItem[]? last_items = nil, - rust = load_rust(), + rust = require('blink.cmp.fuzzy.rust'), } ---@param db_path string diff --git a/fuzzy/lib.rs b/lua/blink/cmp/fuzzy/lib.rs similarity index 100% rename from fuzzy/lib.rs rename to lua/blink/cmp/fuzzy/lib.rs diff --git a/lua/blink/cmp/fuzzy/rust-win.dll b/lua/blink/cmp/fuzzy/rust.dll similarity index 100% rename from lua/blink/cmp/fuzzy/rust-win.dll rename to lua/blink/cmp/fuzzy/rust.dll diff --git a/lua/blink/cmp/fuzzy/rust-macos.dylib b/lua/blink/cmp/fuzzy/rust.dylib similarity index 100% rename from lua/blink/cmp/fuzzy/rust-macos.dylib rename to lua/blink/cmp/fuzzy/rust.dylib diff --git a/lua/blink/cmp/fuzzy/rust-linux.so b/lua/blink/cmp/fuzzy/rust.so similarity index 100% rename from lua/blink/cmp/fuzzy/rust-linux.so rename to lua/blink/cmp/fuzzy/rust.so From cb446cea599631d44a6af24767b4eff7d37746f6 Mon Sep 17 00:00:00 2001 From: Liam Dyer Date: Fri, 18 Oct 2024 14:52:11 -0400 Subject: [PATCH 07/11] fix: buffer source rust path --- lua/blink/cmp/sources/buffer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/blink/cmp/sources/buffer.lua b/lua/blink/cmp/sources/buffer.lua index 3330de7f7..8ce249633 100644 --- a/lua/blink/cmp/sources/buffer.lua +++ b/lua/blink/cmp/sources/buffer.lua @@ -53,7 +53,7 @@ local function run_sync(buf_text, callback) callback(words_to_items(require('bli local function run_async(buf_text, callback) local worker = uv.new_work( -- must use ffi directly since the normal one requires the config which isnt present - function(items) return table.concat(require('libblink_cmp_fuzzy').get_words(items), '\n') end, + function(items) return table.concat(require('blink.cmp.fuzzy.rust').get_words(items), '\n') end, function(words) local items = words_to_items(vim.split(words, '\n')) vim.schedule(function() callback(items) end) From 9c39342f648df8b62816e3b68e7207b20b700706 Mon Sep 17 00:00:00 2001 From: Liam Dyer Date: Fri, 18 Oct 2024 15:03:54 -0400 Subject: [PATCH 08/11] feat: to be squashed --- .github/workflows/release.yaml | 11 ----------- rust-toolchain.toml | 1 - 2 files changed, 12 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 06f108ee9..8d523c224 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -30,11 +30,6 @@ jobs: target: aarch64-apple-darwin artifact_name: target/aarch64-apple-darwin/release/libblink_cmp_fuzzy.dylib - # Windows builds - - os: windows-latest - target: x86_64-pc-windows-msvc - artifact_name: target/x86_64-pc-windows-msvc/release/blink_cmp_fuzzy.dll - steps: - uses: actions/checkout@v4 @@ -58,12 +53,6 @@ jobs: MACOSX_DEPLOYMENT_TARGET="13" cargo build --release --target ${{ matrix.target }} mv "${{ matrix.artifact_name }}" "${{ matrix.target }}.dylib" - - name: Build for Windows - if: contains(matrix.os, 'windows') - run: | - cargo build --release --target ${{ matrix.target }} - mv "${{ matrix.artifact_name }}" "${{ matrix.target }}.dll" - - name: Upload artifacts uses: actions/upload-artifact@v4 with: diff --git a/rust-toolchain.toml b/rust-toolchain.toml index cd9725832..5d56faf9a 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,2 @@ [toolchain] channel = "nightly" -components = [ "rustfmt", "rustc-dev", "rust-analyzer" ] From 00159b64ca12e38e90a31c1cdcac1d6960c92d54 Mon Sep 17 00:00:00 2001 From: Liam Dyer Date: Fri, 18 Oct 2024 15:04:03 -0400 Subject: [PATCH 09/11] feat: add back download script --- lua/blink/cmp/fuzzy/download.lua | 143 +++++++++++++++++++++++++++++++ lua/blink/cmp/init.lua | 105 ++++++++++++----------- 2 files changed, 199 insertions(+), 49 deletions(-) create mode 100644 lua/blink/cmp/fuzzy/download.lua diff --git a/lua/blink/cmp/fuzzy/download.lua b/lua/blink/cmp/fuzzy/download.lua new file mode 100644 index 000000000..8dbad44e7 --- /dev/null +++ b/lua/blink/cmp/fuzzy/download.lua @@ -0,0 +1,143 @@ +local download_config = require('blink.cmp.config').fuzzy.prebuiltBinaries + +local download = {} + +--- @return string +function download.get_lib_extension() + if jit.os:lower() == 'mac' or jit.os:lower() == 'osx' then return '.dylib' end + if jit.os:lower() == 'windows' then return '.dll' end + return '.so' +end + +local root_dir = debug.getinfo(1).source:match('@?(.*/)') +local lib_path = root_dir .. '../../../../target/release/libblink_cmp_fuzzy' .. download.get_lib_extension() +local version_path = root_dir .. '../../../../target/release/version.txt' + +--- @param callback fun(err: string | nil) +function download.ensure_downloaded(callback) + local function cb(err) + vim.schedule(function() callback(err) end) + end + + if not download_config.download then return cb() end + + download.get_git_tag(function(git_version_err, git_version) + if git_version_err then return cb(git_version_err) end + + download.get_downloaded_version(function(version_err, version) + download.is_downloaded(function(downloaded) + local target_version = download_config.forceVersion or git_version + + -- not built locally, not a git tag, error + if not downloaded and not target_version then + return cb( + "Can't download from github due to not being on a git tag and no fuzzy.prebuiltBinaries.forceVersion set, but found no built version of the library. " + .. 'Either run `cargo build --release` via your package manager, switch to a git tag, or set `fuzzy.prebuiltBinaries.forceVersion` in config. ' + .. 'See the README for more info.' + ) + end + -- built locally, ignore + if downloaded and (version_err or version == nil) then return cb() end + -- already downloaded and the correct version + if version == target_version and downloaded then return cb() end + -- unknown state + if not target_version then return cb('Unknown error while getting pre-built binary. Consider re-installing') end + + -- download from github and set version + download.from_github(target_version, function(download_err) + if download_err then return cb(download_err) end + download.set_downloaded_version(target_version, function(set_err) + if set_err then return cb(set_err) end + cb() + end) + end) + end) + end) + end) +end + +--- @param cb fun(downloaded: boolean) +function download.is_downloaded(cb) + vim.uv.fs_stat(lib_path, function(err) + if not err then + return cb(true) + else + -- If not found, check without 'lib' prefix + vim.uv.fs_stat(string.gsub(lib_path, 'libblink_cmp_fuzzy', 'blink_cmp_fuzzy'), function(error) cb(not error) end) + end + end) +end + +--- @param cb fun(err: string | nil, tag: string | nil) +function download.get_git_tag(cb) + vim.system({ 'git', 'describe', '--tags', '--exact-match' }, { cwd = root_dir }, function(out) + if out.code == 128 then return cb() end + if out.code ~= 0 then + return cb('While getting git tag, git exited with code ' .. out.code .. ': ' .. out.stderr) + end + local lines = vim.split(out.stdout, '\n') + if not lines[1] then return cb('Expected atleast 1 line of output from git describe') end + return cb(nil, lines[1]) + end) +end + +--- @param tag string +--- @param cb fun(err: string | nil) +function download.from_github(tag, cb) + local system_triple = download.get_system_triple() + if not system_triple then + return cb( + 'Your system is not supported by pre-built binaries. You must run cargo build --release via your package manager with rust nightly. See the README for more info.' + ) + end + + local url = 'https://github.com/saghen/blink.cmp/releases/download/' + .. tag + .. '/' + .. system_triple + .. download.get_lib_extension() + + vim.system({ 'curl', '--create-dirs', '-Lo', lib_path, url }, {}, function(out) + if out.code ~= 0 then cb('Failed to download pre-build binaries: ' .. out.stderr) end + cb() + end) +end + +--- @param cb fun(err: string | nil, last_version: string | nil) +function download.get_downloaded_version(cb) + return vim.uv.fs_open(version_path, 'r', 438, function(open_err, fd) + if open_err or fd == nil then return cb(open_err or 'Unknown error') end + vim.uv.fs_read(fd, 8, 0, function(read_err, data) + vim.uv.fs_close(fd, function() end) + if read_err or data == nil then return cb(read_err or 'Unknown error') end + return cb(nil, data) + end) + end) +end + +--- @param version string +--- @param cb fun(err: string | nil) +function download.set_downloaded_version(version, cb) + return vim.uv.fs_open(version_path, 'w', 438, function(open_err, fd) + if open_err or fd == nil then return cb(open_err or 'Unknown error') end + vim.uv.fs_write(fd, version, 0, function(write_err) + vim.uv.fs_close(fd, function() end) + if write_err then return cb(write_err) end + return cb() + end) + end) +end + +--- @return string | nil +function download.get_system_triple() + if jit.os:lower() == 'mac' or jit.os:lower() == 'osx' then + if jit.arch:lower():match('arm') then return 'aarch64-apple-darwin' end + if jit.arch:lower():match('x64') then return 'x86_64-apple-darwin' end + end + if jit.os:lower() ~= 'windows' then + if jit.arch:lower():match('arm') then return 'aarch64-unknown-linux-gnu' end + if jit.arch:lower():match('x64') then return 'x86_64-unknown-linux-gnu' end + end +end + +return download diff --git a/lua/blink/cmp/init.lua b/lua/blink/cmp/init.lua index 25ebae095..b45e0b10a 100644 --- a/lua/blink/cmp/init.lua +++ b/lua/blink/cmp/init.lua @@ -5,60 +5,67 @@ cmp.setup = function(opts) local config = require('blink.cmp.config') config.merge_with(opts) - cmp.add_default_highlights() - - require('blink.cmp.keymap').setup(config.keymap) - - -- STRUCTURE - -- trigger -> sources -> fuzzy (filter/sort) -> windows (render) - - -- trigger controls when to show the window and the current context for caching - -- TODO: add first_trigger event for setting up the rest of the plugin - cmp.trigger = require('blink.cmp.trigger.completion').activate_autocmds() - - -- sources fetch autocomplete items, documentation and signature help - cmp.sources = require('blink.cmp.sources.lib') - cmp.sources.register() - - -- windows render and apply completion items and signature help - cmp.windows = { - autocomplete = require('blink.cmp.windows.autocomplete').setup(), - documentation = require('blink.cmp.windows.documentation').setup(), - } - - -- fuzzy combines smith waterman with frecency - -- and bonus from proximity words but I'm still working - -- on tuning the weights - --- @param context blink.cmp.Context - --- @param items blink.cmp.CompletionItem[] | nil - local function update_completions(context, items) - if not cmp.fuzzy then - cmp.fuzzy = require('blink.cmp.fuzzy') - cmp.fuzzy.init_db(vim.fn.stdpath('data') .. '/blink/cmp/fuzzy.db') + require('blink.cmp.fuzzy.download').ensure_downloaded(function(err) + if err then + vim.notify('Error while downloading blink.cmp pre-built binary: ' .. err, vim.log.levels.ERROR) + return end - -- we avoid adding 1-4ms to insertion latency by scheduling for later - vim.schedule(function() - local filtered_items = cmp.fuzzy.filter_items_with_cache(cmp.fuzzy.get_query(), context, items) - if #filtered_items > 0 then - cmp.windows.autocomplete.open_with_items(context, filtered_items) - else - cmp.windows.autocomplete.close() + + cmp.add_default_highlights() + + require('blink.cmp.keymap').setup(config.keymap) + + -- STRUCTURE + -- trigger -> sources -> fuzzy (filter/sort) -> windows (render) + + -- trigger controls when to show the window and the current context for caching + -- TODO: add first_trigger event for setting up the rest of the plugin + cmp.trigger = require('blink.cmp.trigger.completion').activate_autocmds() + + -- sources fetch autocomplete items, documentation and signature help + cmp.sources = require('blink.cmp.sources.lib') + cmp.sources.register() + + -- windows render and apply completion items and signature help + cmp.windows = { + autocomplete = require('blink.cmp.windows.autocomplete').setup(), + documentation = require('blink.cmp.windows.documentation').setup(), + } + + -- fuzzy combines smith waterman with frecency + -- and bonus from proximity words but I'm still working + -- on tuning the weights + --- @param context blink.cmp.Context + --- @param items blink.cmp.CompletionItem[] | nil + local function update_completions(context, items) + if not cmp.fuzzy then + cmp.fuzzy = require('blink.cmp.fuzzy') + cmp.fuzzy.init_db(vim.fn.stdpath('data') .. '/blink/cmp/fuzzy.db') end + -- we avoid adding 1-4ms to insertion latency by scheduling for later + vim.schedule(function() + local filtered_items = cmp.fuzzy.filter_items_with_cache(cmp.fuzzy.get_query(), context, items) + if #filtered_items > 0 then + cmp.windows.autocomplete.open_with_items(context, filtered_items) + else + cmp.windows.autocomplete.close() + end + end) + end + + cmp.trigger.listen_on_show(function(context) + update_completions(context) -- immediately update via cache on keystroke + cmp.sources.request_completions(context) end) - end + cmp.trigger.listen_on_hide(function() + cmp.sources.cancel_completions() + cmp.windows.autocomplete.close() + end) + cmp.sources.listen_on_completions(update_completions) - cmp.trigger.listen_on_show(function(context) - update_completions(context) -- immediately update via cache on keystroke - cmp.sources.request_completions(context) - end) - cmp.trigger.listen_on_hide(function() - cmp.sources.cancel_completions() - cmp.windows.autocomplete.close() + -- setup signature help if enabled + if config.trigger.signature_help.enabled then cmp.setup_signature_help() end end) - cmp.sources.listen_on_completions(update_completions) - - -- setup signature help if enabled - if config.trigger.signature_help.enabled then cmp.setup_signature_help() end end cmp.setup_signature_help = function() From d17ad330248825c4bff795fc7dc4d3f04809bb99 Mon Sep 17 00:00:00 2001 From: Liam Dyer Date: Fri, 18 Oct 2024 21:40:40 -0400 Subject: [PATCH 10/11] feat: drop unwraps, use cpath for rust loading --- flake.nix | 1 - lua/blink/cmp/fuzzy/frecency.rs | 98 +++++++++++++++++++++++++-------- lua/blink/cmp/fuzzy/fuzzy.rs | 61 ++++++++++++-------- lua/blink/cmp/fuzzy/init.lua | 23 ++++---- lua/blink/cmp/fuzzy/lib.rs | 38 +++++++++---- lua/blink/cmp/fuzzy/rust.dll | 1 - lua/blink/cmp/fuzzy/rust.dylib | 1 - lua/blink/cmp/fuzzy/rust.lua | 20 +++++++ lua/blink/cmp/fuzzy/rust.so | 1 - 9 files changed, 168 insertions(+), 76 deletions(-) delete mode 120000 lua/blink/cmp/fuzzy/rust.dll delete mode 120000 lua/blink/cmp/fuzzy/rust.dylib create mode 100644 lua/blink/cmp/fuzzy/rust.lua delete mode 120000 lua/blink/cmp/fuzzy/rust.so diff --git a/flake.nix b/flake.nix index 0238cda63..ede60a96f 100644 --- a/flake.nix +++ b/flake.nix @@ -63,7 +63,6 @@ else "so"; in { - # TODO: I'm not sure how this will change blink-cmp = pkgs.vimUtils.buildVimPlugin { pname = "blink-cmp"; inherit src version; diff --git a/lua/blink/cmp/fuzzy/frecency.rs b/lua/blink/cmp/fuzzy/frecency.rs index 457b39613..11a6bcd0b 100644 --- a/lua/blink/cmp/fuzzy/frecency.rs +++ b/lua/blink/cmp/fuzzy/frecency.rs @@ -1,6 +1,7 @@ use crate::fuzzy::LspItem; use heed::types::*; use heed::{Database, Env, EnvOpenOptions}; +use mlua::Result as LuaResult; use serde::{Deserialize, Serialize}; use std::fs; use std::time::{SystemTime, UNIX_EPOCH}; @@ -30,38 +31,68 @@ pub struct FrecencyTracker { } impl FrecencyTracker { - pub fn new(db_path: &str) -> Self { - fs::create_dir_all(db_path).unwrap(); - let env = unsafe { EnvOpenOptions::new().open(db_path).unwrap() }; - env.clear_stale_readers().unwrap(); + pub fn new(db_path: &str) -> LuaResult { + fs::create_dir_all(db_path).map_err(|err| { + mlua::Error::RuntimeError( + "Failed to create frecency database directory: ".to_string() + &err.to_string(), + ) + })?; + let env = unsafe { + EnvOpenOptions::new().open(db_path).map_err(|err| { + mlua::Error::RuntimeError( + "Failed to open frecency database: ".to_string() + &err.to_string(), + ) + })? + }; + env.clear_stale_readers().map_err(|err| { + mlua::Error::RuntimeError( + "Failed to clear stale readers for frecency database: ".to_string() + + &err.to_string(), + ) + })?; // we will open the default unnamed database - let mut wtxn = env.write_txn().unwrap(); - let db = env.create_database(&mut wtxn, None).unwrap(); + let mut wtxn = env.write_txn().map_err(|err| { + mlua::Error::RuntimeError( + "Failed to open write transaction for frecency database: ".to_string() + + &err.to_string(), + ) + })?; + let db = env.create_database(&mut wtxn, None).map_err(|err| { + mlua::Error::RuntimeError( + "Failed to create frecency database: ".to_string() + &err.to_string(), + ) + })?; let access_thresholds = [ - (1., 1000 * 60 * 2), // 2 minutes - (0.5, 1000 * 60 * 60), // 1 hour - (0.2, 1000 * 60 * 60 * 24), // 1 day - (0.1, 1000 * 60 * 60 * 24 * 7), // 1 week + (1., 1000 * 60 * 2), // 2 minutes + (0.2, 1000 * 60 * 60), // 1 hour + (0.1, 1000 * 60 * 60 * 24), // 1 day + (0.05, 1000 * 60 * 60 * 24 * 7), // 1 week ] .to_vec(); - FrecencyTracker { + Ok(FrecencyTracker { env: env.clone(), db, access_thresholds, - } + }) } - fn get_accesses(&self, item: &LspItem) -> Option> { - let rtxn = self - .env - .read_txn() - .expect("Failed to start read transaction"); + fn get_accesses(&self, item: &LspItem) -> LuaResult>> { + let rtxn = self.env.read_txn().map_err(|err| { + mlua::Error::RuntimeError( + "Failed to start read transaction for frecency database: ".to_string() + + &err.to_string(), + ) + })?; self.db .get(&rtxn, &CompletionItemKey::from(item)) - .expect("Failed to read from database") + .map_err(|err| { + mlua::Error::RuntimeError( + "Failed to read from frecency database: ".to_string() + &err.to_string(), + ) + }) } fn get_now(&self) -> u64 { @@ -71,18 +102,37 @@ impl FrecencyTracker { .as_secs() } - pub fn access(&mut self, item: &LspItem) -> Result<(), heed::Error> { - let mut wtxn = self.env.write_txn()?; - let mut accesses = self.get_accesses(item).unwrap_or_default(); + pub fn access(&mut self, item: &LspItem) -> LuaResult<()> { + let mut wtxn = self.env.write_txn().map_err(|err| { + mlua::Error::RuntimeError( + "Failed to start write transaction for frecency database: ".to_string() + + &err.to_string(), + ) + })?; + + let mut accesses = self.get_accesses(item)?.unwrap_or_default(); accesses.push(self.get_now()); + self.db - .put(&mut wtxn, &CompletionItemKey::from(item), &accesses)?; - wtxn.commit()?; + .put(&mut wtxn, &CompletionItemKey::from(item), &accesses) + .map_err(|err| { + mlua::Error::RuntimeError( + "Failed to write to frecency database: ".to_string() + &err.to_string(), + ) + })?; + + wtxn.commit().map_err(|err| { + mlua::Error::RuntimeError( + "Failed to commit write transaction for frecency database: ".to_string() + + &err.to_string(), + ) + })?; + Ok(()) } pub fn get_score(&self, item: &LspItem) -> i64 { - let accesses = self.get_accesses(item).unwrap_or_default(); + let accesses = self.get_accesses(item).unwrap_or(None).unwrap_or_default(); let now = self.get_now(); let mut score = 0.0; 'outer: for access in &accesses { diff --git a/lua/blink/cmp/fuzzy/fuzzy.rs b/lua/blink/cmp/fuzzy/fuzzy.rs index 6491a95a5..2b5c18558 100644 --- a/lua/blink/cmp/fuzzy/fuzzy.rs +++ b/lua/blink/cmp/fuzzy/fuzzy.rs @@ -23,23 +23,27 @@ pub struct LspItem { impl FromLua<'_> for LspItem { fn from_lua(value: LuaValue<'_>, _lua: &'_ Lua) -> LuaResult { if let Some(tab) = value.as_table() { - let label: String = tab.get("label").unwrap_or_default(); - let sort_text: Option = tab.get("sortText").ok(); - let filter_text: Option = tab.get("filterText").ok(); - let kind: u32 = tab.get("kind").unwrap_or_default(); - let score_offset: Option = tab.get("score_offset").ok(); - let source: String = tab.get("source").unwrap_or_default(); - - Ok(LspItem { - label, - sort_text, - filter_text, - kind, - score_offset, - source, - }) + let label: String = tab.get("label").unwrap_or_default(); + let sort_text: Option = tab.get("sortText").ok(); + let filter_text: Option = tab.get("filterText").ok(); + let kind: u32 = tab.get("kind").unwrap_or_default(); + let score_offset: Option = tab.get("score_offset").ok(); + let source: String = tab.get("source").unwrap_or_default(); + + Ok(LspItem { + label, + sort_text, + filter_text, + kind, + score_offset, + source, + }) } else { - Err(mlua::Error::FromLuaConversionError { from: "LuaValue" , to: "LspItem", message: None }) + Err(mlua::Error::FromLuaConversionError { + from: "LuaValue", + to: "LspItem", + message: None, + }) } } } @@ -78,7 +82,11 @@ impl FromLua<'_> for FuzzyOptions { sorts, }) } else { - Err(mlua::Error::FromLuaConversionError { from: "LuaValue", to: "FuzzyOptions", message: None }) + Err(mlua::Error::FromLuaConversionError { + from: "LuaValue", + to: "FuzzyOptions", + message: None, + }) } } } @@ -108,13 +116,18 @@ pub fn fuzzy( let match_scores = matches .iter() .map(|mtch| { - (mtch.score as i32) - + frecency.get_score(&haystack[mtch.index_in_haystack]) as i32 - + nearby_words - .get(&haystack[mtch.index_in_haystack].label) - .map(|_| 2) - .unwrap_or(0) - + haystack[mtch.index_in_haystack].score_offset.unwrap_or(0) + let frecency_score = if opts.use_frecency { + frecency.get_score(&haystack[mtch.index_in_haystack]) as i32 + } else { + 0 + }; + let nearby_words_score = nearby_words + .get(&haystack[mtch.index_in_haystack].label) + .map(|_| 2) + .unwrap_or(0); + let score_offset = haystack[mtch.index_in_haystack].score_offset.unwrap_or(0); + + (mtch.score as i32) + frecency_score + nearby_words_score + score_offset }) .collect::>(); diff --git a/lua/blink/cmp/fuzzy/init.lua b/lua/blink/cmp/fuzzy/init.lua index 076bb9b71..b6338b5d4 100644 --- a/lua/blink/cmp/fuzzy/init.lua +++ b/lua/blink/cmp/fuzzy/init.lua @@ -40,18 +40,17 @@ function fuzzy.filter_items(needle, haystack) -- perform fuzzy search local filtered_items = {} - local matched_indices = - fuzzy.rust.fuzzy(needle, haystack, { - -- each matching char is worth 4 points and it receives a bonus for capitalization, delimiter and prefix - -- so this should generally be good - -- TODO: make this configurable - min_score = 6 * needle:len(), - max_items = config.fuzzy.max_items, - use_frecency = config.fuzzy.use_frecency, - use_proximity = config.fuzzy.use_proximity, - sorts = config.fuzzy.sorts, - nearby_words = nearby_words, - }) + local matched_indices = fuzzy.rust.fuzzy(needle, haystack, { + -- each matching char is worth 4 points and it receives a bonus for capitalization, delimiter and prefix + -- so this should generally be good + -- TODO: make this configurable + min_score = 6 * needle:len(), + max_items = config.fuzzy.max_items, + use_frecency = config.fuzzy.use_frecency, + use_proximity = config.fuzzy.use_proximity, + sorts = config.fuzzy.sorts, + nearby_words = nearby_words, + }) for _, idx in ipairs(matched_indices) do table.insert(filtered_items, haystack[idx + 1]) diff --git a/lua/blink/cmp/fuzzy/lib.rs b/lua/blink/cmp/fuzzy/lib.rs index 4309e95bc..db94d36c6 100644 --- a/lua/blink/cmp/fuzzy/lib.rs +++ b/lua/blink/cmp/fuzzy/lib.rs @@ -15,28 +15,38 @@ lazy_static! { } pub fn init_db(_: &Lua, db_path: String) -> LuaResult { - let mut frecency = FRECENCY.write().unwrap(); + let mut frecency = FRECENCY.write().map_err(|_| { + mlua::Error::RuntimeError("Failed to acquire lock for frecency".to_string()) + })?; if frecency.is_some() { return Ok(false); } - *frecency = Some(FrecencyTracker::new(&db_path)); + *frecency = Some(FrecencyTracker::new(&db_path)?); Ok(true) } pub fn destroy_db(_: &Lua, _: ()) -> LuaResult { - // todo: there should be a way to get rid of old locks - // since a crash would result in a leak - let frecency = FRECENCY.write().unwrap(); + let frecency = FRECENCY.write().map_err(|_| { + mlua::Error::RuntimeError("Failed to acquire lock for frecency".to_string()) + })?; drop(frecency); - let mut frecency = FRECENCY.write().unwrap(); + + let mut frecency = FRECENCY.write().map_err(|_| { + mlua::Error::RuntimeError("Failed to acquire lock for frecency".to_string()) + })?; *frecency = None; + Ok(true) } pub fn access(_: &Lua, item: LspItem) -> LuaResult { - let mut frecency_handle = FRECENCY.write().unwrap(); - let frecency = frecency_handle.as_mut().unwrap(); - frecency.access(&item).unwrap(); + let mut frecency_handle = FRECENCY.write().map_err(|_| { + mlua::Error::RuntimeError("Failed to acquire lock for frecency".to_string()) + })?; + let frecency = frecency_handle.as_mut().ok_or_else(|| { + mlua::Error::RuntimeError("Attempted to use frencecy before initialization".to_string()) + })?; + frecency.access(&item)?; Ok(true) } @@ -44,8 +54,12 @@ pub fn fuzzy( _lua: &Lua, (needle, haystack, opts): (String, Vec, FuzzyOptions), ) -> LuaResult> { - let mut frecency_handle = FRECENCY.write().unwrap(); - let frecency = frecency_handle.as_mut().unwrap(); + let mut frecency_handle = FRECENCY.write().map_err(|_| { + mlua::Error::RuntimeError("Failed to acquire lock for frecency".to_string()) + })?; + let frecency = frecency_handle.as_mut().ok_or_else(|| { + mlua::Error::RuntimeError("Attempted to use frencecy before initialization".to_string()) + })?; Ok(fuzzy::fuzzy(needle, haystack, frecency, opts) .into_iter() @@ -63,7 +77,7 @@ pub fn get_words(_: &Lua, text: String) -> LuaResult> { } #[mlua::lua_module] -fn blink_cmp_fuzzy_rust(lua: &Lua) -> LuaResult { +fn blink_cmp_fuzzy(lua: &Lua) -> LuaResult { let exports = lua.create_table()?; exports.set("fuzzy", lua.create_function(fuzzy)?)?; exports.set("get_words", lua.create_function(get_words)?)?; diff --git a/lua/blink/cmp/fuzzy/rust.dll b/lua/blink/cmp/fuzzy/rust.dll deleted file mode 120000 index 9fa2797f3..000000000 --- a/lua/blink/cmp/fuzzy/rust.dll +++ /dev/null @@ -1 +0,0 @@ -../../../../target/release/blink_cmp_fuzzy.dll \ No newline at end of file diff --git a/lua/blink/cmp/fuzzy/rust.dylib b/lua/blink/cmp/fuzzy/rust.dylib deleted file mode 120000 index 9ed65aa1a..000000000 --- a/lua/blink/cmp/fuzzy/rust.dylib +++ /dev/null @@ -1 +0,0 @@ -../../../../target/release/libblink_cmp_fuzzy.dylib \ No newline at end of file diff --git a/lua/blink/cmp/fuzzy/rust.lua b/lua/blink/cmp/fuzzy/rust.lua new file mode 100644 index 000000000..e2374cfc9 --- /dev/null +++ b/lua/blink/cmp/fuzzy/rust.lua @@ -0,0 +1,20 @@ +--- @return string +local function get_lib_extension() + if jit.os:lower() == 'mac' or jit.os:lower() == 'osx' then return '.dylib' end + if jit.os:lower() == 'windows' then return '.dll' end + return '.so' +end + +-- search for the lib in the /target/release directory with and without the lib prefix +-- since MSVC doesn't include the prefix +package.cpath = package.cpath + .. ';' + .. debug.getinfo(1).source:match('@?(.*/)') + .. '../../../../target/release/lib?' + .. get_lib_extension() + .. ';' + .. debug.getinfo(1).source:match('@?(.*/)') + .. '../../../../target/release/?' + .. get_lib_extension() + +return require('blink_cmp_fuzzy') diff --git a/lua/blink/cmp/fuzzy/rust.so b/lua/blink/cmp/fuzzy/rust.so deleted file mode 120000 index 969aa9a59..000000000 --- a/lua/blink/cmp/fuzzy/rust.so +++ /dev/null @@ -1 +0,0 @@ -../../../../target/release/libblink_cmp_fuzzy.so \ No newline at end of file From 9738b20329ef5515f31f88ca716293e1393b7283 Mon Sep 17 00:00:00 2001 From: Liam Dyer Date: Fri, 18 Oct 2024 21:52:54 -0400 Subject: [PATCH 11/11] feat: misc download cleanups --- lua/blink/cmp/fuzzy/download.lua | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/lua/blink/cmp/fuzzy/download.lua b/lua/blink/cmp/fuzzy/download.lua index e66a36d7d..2059c0454 100644 --- a/lua/blink/cmp/fuzzy/download.lua +++ b/lua/blink/cmp/fuzzy/download.lua @@ -59,15 +59,13 @@ end --- @param cb fun(downloaded: boolean) function download.is_downloaded(cb) vim.uv.fs_stat(download.lib_path, function(err) - if not err then - return cb(true) - else - -- If not found, check without 'lib' prefix - vim.uv.fs_stat( - string.gsub(download.lib_path, 'libblink_cmp_fuzzy', 'blink_cmp_fuzzy'), - function(error) cb(not error) end - ) - end + if not err then return cb(true) end + + -- If not found, check without 'lib' prefix + vim.uv.fs_stat( + string.gsub(download.lib_path, 'libblink_cmp_fuzzy', 'blink_cmp_fuzzy'), + function(error) cb(not error) end + ) end) end @@ -100,7 +98,7 @@ function download.from_github(tag, cb) .. system_triple .. download.get_lib_extension() - vim.system({ 'curl', '--create-dirs', '-Lo', download.lib_path, url }, {}, function(out) + vim.system({ 'curl', '--create-dirs', '-fLo', download.lib_path, url }, {}, function(out) if out.code ~= 0 then cb('Failed to download pre-build binaries: ' .. out.stderr) end cb() end)