diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 000000000..9037819ed --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,23 @@ +[target.x86_64-apple-darwin] +rustflags = ["-C", "link-args=-rdynamic"] + +[target.x86_64-unknown-linux-gnu] +rustflags = ["-C", "link-args=-rdynamic"] + +# Since autotools sets this and we are *not* forcing it here, this will not +# affect release builds. It will affect `cargo run` and make it easier to test +# locally since the Lua loader path will be relative to the current sources. +# For debug builds it is assumed you configured `--without-system-luarocks`, +# this convenience won't enable you to use system packages in debug builds. +[env] +SILE_PATH = { value = "", relative = true } + +[target.'cfg(all())'] +rustflags = [ + # CLIPPY LINT SETTINGS + # This is a workaround to configure lints for the entire workspace, pending the ability to configure this via TOML. + # See: `https://github.com/rust-lang/cargo/issues/5034` + # `https://github.com/EmbarkStudios/rust-ecosystem/issues/22#issuecomment-947011395` + "-Aclippy::clone_double_ref", + "-Aclippy::ptr_arg", +] diff --git a/.cirrus.yml b/.cirrus.yml index fe2e5dbc7..34f9860a6 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -2,7 +2,7 @@ task: name: Cirrus CI (FreeBSD) freebsd_instance: matrix: - - image_family: freebsd-13-0 + - image_family: freebsd-13-2 - image_family: freebsd-12-3 env: MAKEFLAGS: -j$(nproc) -Otarget @@ -23,10 +23,8 @@ task: folder: /usr/local/lib/lua fingerprint_script: cat sile.rockspec.in dependencies_script: - - pkg install -y autoconf automake fontconfig GentiumPlus git gmake harfbuzz libtool pkgconf png - - pkg install -y lua54 lua54-lpeg lua54-luafilesystem lua54-luarocks lua54-luasec lua54-luasocket - # lua54-luaexpat exists but seems boken on 13.0, system doesn't have expat 2.4+ so 1.5.x isn't an option either - - luarocks54 install luaexpat 1.4.1 + - pkg install -y autoconf automake fontconfig GentiumPlus git gmake harfbuzz jq libtool pkgconf png rust + - pkg install -y lua54 lua54-luaexpat lua54-lpeg lua54-luafilesystem lua54-luarocks lua54-luasec lua54-luasocket - luarocks54 install cassowary - luarocks54 install cldr - luarocks54 install compat53 @@ -46,7 +44,7 @@ task: - ./bootstrap.sh configure_script: | ./configure MAKE=gmake \ - --enable-developer LUAROCKS=false LUACHECK=false BUSTED=false NIX=false \ + --enable-developer LUAROCKS=false LUACHECK=false BUSTED=false PDFINFO=false NIX=false \ --disable-font-variations \ --with-system-luarocks \ --without-manual diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ae604c6ea..51e8713d9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,11 +31,12 @@ jobs: - name: Install system dependencies run: | sudo apt-get update - sudo apt-get install fonts-sil-gentiumplus ghostscript graphviz libarchive-tools libfontconfig1-dev libharfbuzz-dev libicu-dev liblua5.3-dev libpng-dev lua5.3 lua-sec lua-socket lua-zlib-dev luarocks poppler-utils + sudo apt-get install cargo fonts-sil-gentiumplus ghostscript graphviz jq libarchive-tools libfontconfig1-dev libharfbuzz-dev libicu-dev libluajit-5.1-dev libpng-dev luajit lua-sec lua-socket lua-zlib-dev luarocks poppler-utils - name: Configure run: | ./bootstrap.sh - ./configure \ + ./configure PDFINFO=false \ + --with-luajit \ --disable-font-variations \ --without-system-luarocks \ --with-manual diff --git a/.github/workflows/rust_lint.yml b/.github/workflows/rust_lint.yml new file mode 100644 index 000000000..25dd6e644 --- /dev/null +++ b/.github/workflows/rust_lint.yml @@ -0,0 +1,42 @@ +name: Rust Lint + +on: [ push, pull_request ] + +jobs: + + rustfmt: + strategy: + fail-fast: false + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + profile: minimal + components: rustfmt + - name: Cache Rust + uses: Swatinem/rust-cache@v2 + - name: Run rustfmt + run: | + git ls-files '*.rs' | xargs rustfmt --check + + clippy: + strategy: + fail-fast: false + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + profile: minimal + components: clippy + - name: Cache Rust + uses: Swatinem/rust-cache@v2 + - uses: actions-rs/clippy-check@v1 + with: + token: ${{ github.token }} + args: -- -D warnings diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b6678af8a..a7c983200 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -39,11 +39,15 @@ jobs: path: | lua_modules key: luarocks-${{ matrix.luaVersion[0] }}-${{ hashFiles('Makefile-luarocks', 'sile.rockspec.in') }} + - name: Cache Rust + uses: Swatinem/rust-cache@v2 - name: Setup ‘lua’ uses: leafo/gh-actions-lua@v10 with: luaVersion: ${{ matrix.luaVersion[0] }} luaCompileFlags: ${{ matrix.luaVersion[1] }} + - name: Setup ‘cargo’ + uses: actions-rs/toolchain@v1 - name: Setup ‘luarocks’ uses: leafo/gh-actions-luarocks@v4 - name: Prep system Lua for use @@ -65,7 +69,7 @@ jobs: - name: Configure run: | ./bootstrap.sh - ./configure \ + ./configure PDFINFO=false \ --enable-developer LUACHECK=false NIX=false \ --disable-font-variations \ --without-system-luarocks \ @@ -82,6 +86,10 @@ jobs: timeout-minutes: ${{ runner.debug && 60 || 6 }} run: | make regressions + - name: Test Cargo + timeout-minutes: ${{ runner.debug && 60 || 6 }} + run: | + make cargo-test - name: Upload artifacts uses: actions/upload-artifact@v3 with: diff --git a/.gitignore b/.gitignore index 76a9c3b23..916392aac 100644 --- a/.gitignore +++ b/.gitignore @@ -79,16 +79,20 @@ gource.webm *.rockspec .fonts/* .sources/* -/sile +sile sile.1 -/.version -/.version-prev -/.tarball-version -/.built-subdirs +sile-lua +sile-lua.1 +.version +.version-prev +.tarball-version +.built-subdirs *.so core/version.lua core/features.lua +target/ +completions/ core/pathsetup.lua # Nix symlink to builds -/result +result/ diff --git a/.luacheckrc b/.luacheckrc index bb102010f..435e7ad47 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -26,8 +26,8 @@ globals = { "luautf8", "pl", "fluent", - "extendSilePath", "executablePath", + "extendSilePath", "SYSTEM_SILE_PATH", "SHARED_LIB_EXT" } diff --git a/.luarc.json b/.luarc.json index 16515bea9..783489dec 100644 --- a/.luarc.json +++ b/.luarc.json @@ -7,8 +7,8 @@ "luautf8", "pl", "fluent", - "extendSilePath", "executablePath", + "extendSilePath", "SYSTEM_SILE_PATH", "SHARED_LIB_EXT" ], diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 000000000..4760bfb8a --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,863 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "342258dd14006105c2b75ab1bd7543a03bdf0cfc94383303ac212a04939dff6f" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-wincon", + "concolor-override", + "concolor-query", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ea9e81bd02e310c216d080f6223c179012256e5151c41db88d12c88a1684d2" + +[[package]] +name = "anstyle-parse" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7d1bb534e9efed14f3e5f44e7dd1a4f709384023a4165199a4241e18dff0116" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-wincon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3127af6145b149f3287bb9a0d10ad9c5692dba8c53ad48285e5bec4063834fa" +dependencies = [ + "anstyle", + "windows-sys 0.45.0", +] + +[[package]] +name = "anyhow" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "memchr", +] + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +dependencies = [ + "jobserver", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "4.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046ae530c528f252094e4a77886ee1374437744b2bff1497aa898bbddbbb29b3" +dependencies = [ + "clap_builder", + "clap_derive", + "once_cell", +] + +[[package]] +name = "clap_builder" +version = "4.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "223163f58c9a40c3b0a43e1c4b50a9ce09f007ea2cb1ec258a687945b4b7929f" +dependencies = [ + "anstream", + "anstyle", + "bitflags", + "clap_lex", + "strsim", + "terminal_size", +] + +[[package]] +name = "clap_complete" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c22dcfb410883764b29953103d9ef7bb8fe21b3fa1158bc99986c2067294bd" +dependencies = [ + "clap", +] + +[[package]] +name = "clap_derive" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.13", +] + +[[package]] +name = "clap_lex" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" + +[[package]] +name = "clap_mangen" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4237e29de9c6949982ba87d51709204504fb8ed2fd38232fcb1e5bf7d4ba48c8" +dependencies = [ + "clap", + "roff", +] + +[[package]] +name = "concolor-override" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f" + +[[package]] +name = "concolor-query" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf" +dependencies = [ + "windows-sys 0.45.0", +] + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "enum-iterator" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "706d9e7cf1c7664859d79cd524e4e53ea2b67ea03c98cc2870c5e539695d597e" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "355f93763ef7b0ae1c43c4d8eccc9d5848d84ad1a1d8ce61c421d1ac85a19d05" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "errno" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.45.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "form_urlencoded" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "getset" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "git2" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf7f68c2995f392c49fffb4f95ae2c873297830eb25c6bc4c114ce8f4562acc" +dependencies = [ + "bitflags", + "libc", + "libgit2-sys", + "log", + "url", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "is-terminal" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "256017f749ab3117e93acb91063009e1f1bb56d03965b14c2c8df4eb02c524d8" +dependencies = [ + "hermit-abi", + "io-lifetimes", + "rustix", + "windows-sys 0.45.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[package]] +name = "jobserver" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +dependencies = [ + "libc", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.141" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" + +[[package]] +name = "libgit2-sys" +version = "0.14.2+1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f3d95f6b51075fe9810a7ae22c7095f12b98005ab364d8544797a825ce946a4" +dependencies = [ + "cc", + "libc", + "libz-sys", + "pkg-config", +] + +[[package]] +name = "libz-sys" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linux-raw-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "lua-src" +version = "544.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "708ba3c844d5e9d38def4a09dd871c17c370f519b3c4b7261fbabe4a613a814c" +dependencies = [ + "cc", +] + +[[package]] +name = "luajit-src" +version = "210.4.5+resty2cf5186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b7992a40e602786272d84c6f2beca44a588ededcfd57b48ec6f82008a7cb97" +dependencies = [ + "cc", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "mlua" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea8ce6788556a67d90567809c7de94dfef2ff1f47ff897aeee935bcfbcdf5735" +dependencies = [ + "bstr", + "cc", + "lua-src", + "luajit-src", + "mlua_derive", + "num-traits", + "once_cell", + "pkg-config", + "rustc-hash", +] + +[[package]] +name = "mlua_derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9214e60d3cf1643013b107330fcd374ccec1e4ba1eef76e7e5da5e8202e71c0" +dependencies = [ + "itertools", + "once_cell", + "proc-macro-error", + "proc-macro2", + "quote", + "regex", + "syn 1.0.109", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "pkg-config" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" + +[[package]] +name = "roff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.37.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aae838e49b3d63e9274e1c01833cc8139d3fec468c3b84688c628f44b1ae11d" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.45.0", +] + +[[package]] +name = "rustversion" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" + +[[package]] +name = "serde" +version = "1.0.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" + +[[package]] +name = "sile" +version = "0.14.8" +dependencies = [ + "anyhow", + "clap", + "clap_complete", + "clap_mangen", + "lazy_static", + "mlua", + "vergen", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "terminal_size" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" +dependencies = [ + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "thiserror" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.13", +] + +[[package]] +name = "time" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" +dependencies = [ + "itoa", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" +dependencies = [ + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "vergen" +version = "7.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f21b881cd6636ece9735721cf03c1fe1e774fe258683d084bb2812ab67435749" +dependencies = [ + "anyhow", + "cfg-if", + "enum-iterator", + "getset", + "git2", + "rustversion", + "thiserror", + "time", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 000000000..c1488851a --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,75 @@ +[package] +name = "sile" +version = "0.14.8" +edition = "2021" +description = "Simon’s Improved Layout Engine" +authors = [ + "Simon Cozens", + "Caleb Maclennan ", + "Olivier Nicole", + "Didier Willis" +] +rust-version = "1.68" +homepage = "https://sile-typesetter.org" +license = "MIT" +build = "build-aux/build.rs" + +[[bin]] +name = "sile" +required-features = ["cli"] + +[dependencies] + + [dependencies.anyhow] + version = "1.0" + + [dependencies.clap] + version = "4.2" + optional = true + features = [ "derive", "string", "wrap_help" ] + + [dependencies.lazy_static] + version = "1.4" + + [dependencies.mlua] + version = "0.8" + features = [ "macros", "vendored" ] + +[build-dependencies] + + [build-dependencies.clap_complete] + version = "4.2" + optional = true + + [build-dependencies.clap_mangen] + version = "0.2" + optional = true + + [build-dependencies.clap] + version = "4.0" + optional = true + features = [ "derive" ] + + [build-dependencies.vergen] + version = "7.4" + default-features = false + features = [ "build", "git" ] + +[features] +default = ["cli", "bash", "elvish", "fish", "manpage", "powershell", "zsh"] +lua54 = ["mlua/lua54"] +lua53 = ["mlua/lua53"] +lua52 = ["mlua/lua52"] +lua51 = ["mlua/lua51"] +luajit = ["mlua/luajit"] +completions = ["cli", "clap_complete"] +cli = ["clap"] +bash = ["completions"] +elvish = ["completions"] +fish = ["completions"] +manpage = ["clap_mangen"] +powershell = ["completions"] +zsh = ["completions"] + +[profile.release] +lto = true diff --git a/Makefile-luarocks b/Makefile-luarocks index 46e5c8ef3..7ea0dc624 100644 --- a/Makefile-luarocks +++ b/Makefile-luarocks @@ -17,4 +17,7 @@ $(LUAMODLOCK): lua_modules $(LUAMODSPEC) $(genrockslock) > $@ else LUAMODLOCK := +LUA_PATH := $(shell lua$(LUA_VERSION) -e 'print(package.path)') +LUA_CPATH := $(shell lua$(LUA_VERSION) -e 'print(package.cpath)') +export LUA_PATH LUA_CPATH endif diff --git a/Makefile.am b/Makefile.am index 95b3f8988..651c1983c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -45,7 +45,7 @@ include $(wildcard Makefile-distfiles) FIGURES = documentation/fig-input-to-output.pdf MANUAL := documentation/sile.pdf -SILE := $(PACKAGE_NAME) +SILELUA := $(PACKAGE_NAME)-lua if MANUAL _MANUAL = $(MANUAL) @@ -55,15 +55,20 @@ endif $(MANUAL): $(FIGURES) nobase_dist_pkgdata_DATA = $(SILEDATA) $(LUALIBRARIES) +nobase_nodist_pkgdata_DATA = core/features.lua core/version.lua $(LUAMODULES) +dist_man_MANS = sile.1 sile-lua.1 nobase_nodist_pkgdata_DATA = core/features.lua core/pathsetup.lua core/version.lua $(LUAMODULES) -dist_man_MANS = sile.1 +dist_man_MANS = sile.1 sile-lua.1 dist_doc_DATA = README.md CHANGELOG.md dist_pdf_DATA = $(_MANUAL) dist_license_DATA = LICENSE lua-libraries/LICENSE-lunamark -bin_SCRIPTS = sile +bin_SCRIPTS = sile-lua +bin_PROGRAMS = sile +sile_SOURCES = Cargo.toml build-aux/build.rs src/bin/sile.rs src/lib.rs src/cli.rs +EXTRA_sile_SOURCES = Cargo.lock .version EXTRA_DIST = spec tests documentation sile-dev-1.rockspec fontconfig.conf EXTRA_DIST += Makefile-distfiles -EXTRA_DIST += build-aux/action-updater.js build-aux/decore-automake.sh build-aux/git-version-gen build-aux/list-dist-files.sh +EXTRA_DIST += build-aux/action-updater.js build-aux/cargo-updater.js build-aux/decore-automake.sh build-aux/git-version-gen build-aux/list-dist-files.sh EXTRA_DIST += Dockerfile build-aux/docker-bootstrap.sh build-aux/docker-fontconfig.conf hooks/build EXTRA_DIST += default.nix flake.nix flake.lock shell.nix EXTRA_DIST += package.json # imported by both Nix and Docker @@ -76,6 +81,85 @@ CLEANFILES = $(bin_SCRIPTS) $(dist_man_MANS) $(BUILT_SOURCES) $(DEPFILES) $(ACTU Makefile-distfiles: $(wildcard .version .tarball-version) | $(LUAMODLOCK) $(SHELL) build-aux/list-dist-files.sh > $@ +if DEBUG_RELEASE +CARGO_RELEASE_ARGS = +else +CARGO_RELEASE_ARGS = --release --locked +endif + +if LUAJIT +MLUAVER = luajit +else +MLUAVER = lua$(LUA_SHORT_VERSION) +endif +CARGO_FEATURE_ARGS = --features $(MLUAVER) + +CARGO_ENV = CARGO_TARGET_DIR=@abs_top_builddir@/target +RUST_BIN = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/$(PACKAGE_NAME) +_RUST_OUT = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/.cargo_out_dir +COMPLETIONS_OUT_DIR = completions + +if ENABLE_BASH_COMPLETION +bashcompletiondir = $(BASH_COMPLETION_DIR) +nodist_bashcompletion_DATA = $(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME) +CLEANFILES += $(nodist_bashcompletion_DATA) +endif + +if ENABLE_FISH_COMPLETION +fishcompletiondir = $(FISH_COMPLETION_DIR) +nodist_fishcompletion_DATA = $(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME).fish +CLEANFILES += $(nodist_fishcompletion_DATA) +endif + +if ENABLE_ZSH_COMPLETION +zshcompletiondir = $(ZSH_COMPLETION_DIR) +nodist_zshcompletion_DATA = $(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME) +CLEANFILES += $(nodist_zshcompletion_DATA) +endif + +export SILE_VERSION = v$(VERSION) +SILE := $(PACKAGE_NAME)$(EXEEXT) + +# Leave some tips for cargo to use so CLI knows where it is +export CONFIGURE_PREFIX = $(prefix)/ +export CONFIGURE_DATADIR = $(datadir)/ +export CONFIGURE_BINDIR = $(bindir)/ + +CARGO_VERBOSE = $(cargo_verbose_$(V)) +cargo_verbose_ = $(cargo_verbose_$(AM_DEFAULT_VERBOSITY)) +cargo_verbose_0 = +cargo_verbose_1 = --verbose + +$(COMPLETIONS_OUT_DIR): + $(MKDIR_P) $@ + +$(SILE): $(RUST_BIN) + $(INSTALL) $(RUST_BIN) $@ + +$(PACKAGE_NAME).1: $(RUST_BIN) + $(INSTALL) -m644 $$(cat $(_RUST_OUT))/$@ $@ + +$(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME): $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) + $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/$(PACKAGE_NAME).bash $@ + +$(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME).elv: $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) + $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/$(PACKAGE_NAME).elv $@ + +$(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME).fish: $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) + $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/$(PACKAGE_NAME).fish $@ + +$(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME).ps1: $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) + $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/_$(PACKAGE_NAME).ps1 $@ + +$(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME): $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) + $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/_$(PACKAGE_NAME) $@ + +$(_RUST_OUT) $(RUST_BIN): $(sile_SOURCES) $(EXTRA_sile_SOURCES) + cd $(top_srcdir) + $(CARGO_ENV) $(CARGO) build $(CARGO_VERBOSE) $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) + $(CARGO_ENV) $(CARGO) build --quiet --message-format=json $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) | + $(JQ) -sr 'map(select(.reason == "build-script-executed")) | last | .out_dir' > $(_RUST_OUT) + _BRANCH_REF != $(AWK) '{print ".git/" $$2}' .git/HEAD 2>/dev/null ||: .version: $(_BRANCH_REF) @@ -140,7 +224,7 @@ DEPDIR := .deps REGRESSIONSCRIPT := ./tests/regressions.pl LOCALTESTFONTS := FONTCONFIG_FILE=$(PWD)/fontconfig.conf SILEFLAGS ?= -m $(DEPDIR)/$(basename $@).d -d versions -f fontconfig -BUSTEDFLAGS ?= $(and $(SILE_COVERAGE),-c) +BUSTEDFLAGS ?= TESTPDFS = $(addsuffix .pdf,$(basename $(TESTSRCS))) EXPECTEDS ?= $(filter $(addsuffix .expected,$(basename $(TESTSRCS))),$(TESTEXPECTS)) @@ -149,10 +233,11 @@ ACTUALS = $(addsuffix .actual,$(basename $(EXPECTEDS))) check: selfcheck .PHONY: selfcheck -selfcheck: | $(_BUILT_SUBDIRS) +selfcheck: | $(SILE) $(_BUILT_SUBDIRS) output=$$(mktemp -t selfcheck-XXXXXX.pdf) trap 'rm -f $$output' EXIT HUP TERM - echo "foo" | ./$(SILE) -o $$output - + export SILE_PATH + echo "foo" | SILE_PATH=$(PWD) ./$(SILE) -o $$output - $(PDFINFO) $$output | $(GREP) "SILE v$(VERSION)" .PHONY: docs @@ -162,7 +247,8 @@ docs: $(MANUAL) # garantee the TOC is up to date, simplify when #230 is fixed. hastoc = [ -f $(subst .pdf,.toc,$@) ] && echo true || echo false pages = $(PDFINFO) $@ | $(AWK) '$$1 == "Pages:" {print $$2}' || echo 0 -silepass = $(LOCALTESTFONTS) ./$(SILE) $(SILEFLAGS) $< -o $@ && pg0=$${pg} pg=$$($(pages)) || false +localsile = $(LOCALTESTFONTS) SILE_PATH=$(PWD) ./$(SILE) $(SILEFLAGS) +silepass = $(localsile) $< -o $@ && pg0=$${pg} pg=$$($(pages)) || false define runsile = set -e pg=$$($(pages)) hadtoc=$$($(hastoc)) @@ -190,7 +276,7 @@ $(_SUBDIR_TELLS): $(MAKE) $(AM_MAKEFLAGS) all-recursive # $(error Running `make install`, `make dist`, or other end-game targets before `make all` unspported.) -patterndeps = $(_FORCED) $(_TEST_DEPS) $(_DOCS_DEPS) | $(DEPDIRS) $(LUAMODLOCK) $(_BUILT_SUBDIRS) +patterndeps = $(_FORCED) $(_TEST_DEPS) $(_DOCS_DEPS) | $(SILE) $(DEPDIRS) $(LUAMODLOCK) $(_BUILT_SUBDIRS) %.pdf: %.sil $$(patterndeps) $(runsile) @@ -208,7 +294,7 @@ patterndeps = $(_FORCED) $(_TEST_DEPS) $(_DOCS_DEPS) | $(DEPDIRS) $(LUAMODLOCK) .PHONY: force force: ; -PHONY_DEVELOPER_TARGETS = regressions test lint luarocks-lint luacheck busted coverage benchmark compare update_expecteds regression_previews docker docker-dep-check docker-ghcr-to-hub docker-build-push gource.webm +PHONY_DEVELOPER_TARGETS = regressions test lint luarocks-lint luacheck rustfmt clippy cargo-test busted coverage benchmark compare update_expecteds regression_previews docker docker-dep-check docker-ghcr-to-hub docker-build-push gource.webm .PHONY: $(PHONY_DEVELOPER_TARGETS) if DEVELOPER @@ -216,9 +302,9 @@ if DEVELOPER regressions: $(TESTSRCS) $(ACTUALS) $(LOCALTESTFONTS) $(REGRESSIONSCRIPT) $(TESTSRCS) -test: regressions busted +test: regressions busted cargo-test -lint: luacheck luarocks-lint +lint: luacheck luarocks-lint rustfmt clippy luarocks-lint: $(LUAMODSPEC) $(LUAROCKS) lint $(LUAMODSPEC) @@ -226,7 +312,18 @@ luarocks-lint: $(LUAMODSPEC) luacheck: $(LUACHECK) -j$(shell nproc) -q . -busted: $(SILE) $(addprefix .fonts/,$(TESTFONTFILES)) $(BUSTEDSPECS) +rustfmt: + $(GIT) ls-files '*.rs' | $(XARGS) rustfmt --check + +clippy: + cd $(srcdir) + $(CARGO_ENV) $(CARGO) $(CARGO_VERBOSE) clippy $(CARGO_FEATURE_ARGS) -- -D warnings + +cargo-test: $(SILE) + cd $(srcdir) + $(CARGO_ENV) $(CARGO) $(CARGO_VERBOSE) test $(CARGO_FEATURE_ARGS) --locked + +busted: $(SILELUA) $(addprefix .fonts/,$(TESTFONTFILES)) $(BUSTEDSPECS) set -f; IFS=';' if SYSTEM_LUAROCKS packagecpath=(./{,core/}?.$(SHARED_LIB_EXT)) @@ -235,10 +332,11 @@ else packagecpath=(./{,core/,lua_modules/lib/lua/$(LUA_VERSION)/}?.$(SHARED_LIB_EXT)) packagepath=(./{,lua_modules/share/lua/$(LUA_VERSION)/,lua-libraries/}?{,/init}.lua) endif - $(LOCALTESTFONTS) $(BUSTED) --cpath="$${packagecpath[*]};;" --lpath="$${packagepath[*]};;" $(BUSTEDFLAGS) . +# Note: use of --lua causes this to be passed back through a shell loosing one layer of quoting. Drop single quotes if removing. + $(LOCALTESTFONTS) $(BUSTED) --lua=$(LUA) --cpath="'$${packagecpath[*]};;'" --lpath="'$${packagepath[*]};;'" $(BUSTEDFLAGS) . coverage: export SILE_COVERAGE=1 -coverage: BUSTEDFLAGS = -c +coverage: BUSTEDFLAGS += -c coverage: regression_previews busted HEADSHA ?= HEAD @@ -263,27 +361,27 @@ time-%.json: benchmark-%/time.json update_expecteds: $(EXPECTEDS) tests/%.expected: tests/%.sil $$(patterndeps) - $(LOCALTESTFONTS) ./$(SILE) $(SILEFLAGS) -b debug $< -o $@ + $(localsile) -b debug $< -o $@ tests/%.expected: tests/%.xml $$(patterndeps) - $(LOCALTESTFONTS) ./$(SILE) $(SILEFLAGS) -b debug $< -o $@ + $(localsile) -b debug $< -o $@ tests/%.expected: tests/%.nil $$(patterndeps) - $(LOCALTESTFONTS) ./$(SILE) $(SILEFLAGS) -b debug $< -o $@ + $(localsile) -b debug $< -o $@ regression_previews: $(TESTPREVIEWS) tests/%.actual: tests/%.sil $$(patterndeps) -$(if $(CLEAN),rm -f $@,:) - $(LOCALTESTFONTS) ./$(SILE) $(SILEFLAGS) -b debug $< -o $@ + $(localsile) -b debug $< -o $@ tests/%.actual: tests/%.xml $$(patterndeps) -$(if $(CLEAN),rm -f $@,:) - $(LOCALTESTFONTS) ./$(SILE) $(SILEFLAGS) -b debug $< -o $@ + $(localsile) -b debug $< -o $@ tests/%.actual: tests/%.nil $$(patterndeps) -$(if $(CLEAN),rm -f $@,:) - $(LOCALTESTFONTS) ./$(SILE) $(SILEFLAGS) -b debug $< -o $@ + $(localsile) -b debug $< -o $@ DEPFILES = $(addsuffix .d,$(addprefix $(DEPDIR)/,$(basename $(TESTSRCS) $(MANUAL)))) DEPDIRS = $(sort $(dir $(DEPFILES))) diff --git a/build-aux/build.rs b/build-aux/build.rs new file mode 100644 index 000000000..a698a8166 --- /dev/null +++ b/build-aux/build.rs @@ -0,0 +1,86 @@ +#[cfg(feature = "completions")] +use clap::CommandFactory; +#[cfg(feature = "completions")] +use clap_complete::generator::generate_to; +#[cfg(feature = "completions")] +use clap_complete::shells::{Bash, Elvish, Fish, PowerShell, Zsh}; +#[cfg(feature = "manpage")] +use clap_mangen::Man; +use std::env; +#[cfg(feature = "completions")] +use std::{fs, path}; +use vergen::{vergen, Config}; + +#[cfg(feature = "completions")] +include!("../src/cli.rs"); + +fn main() { + let mut flags = Config::default(); + if let Ok(val) = env::var("SILE_VERSION") { + *flags.git_mut().semver_mut() = false; + println!("cargo:rustc-env=VERGEN_GIT_SEMVER={val}") + }; + if vergen(flags).is_err() { + let mut flags = Config::default(); + *flags.git_mut().enabled_mut() = false; + vergen(flags).expect("Unable to generate the cargo keys!"); + } + #[cfg(feature = "manpage")] + generate_manpage(); + #[cfg(feature = "completions")] + generate_shell_completions(); +} + +/// Generate man page +#[cfg(feature = "manpage")] +fn generate_manpage() { + let out_dir = match env::var_os("OUT_DIR") { + None => return, + Some(out_dir) => out_dir, + }; + let manpage_dir = path::Path::new(&out_dir); + fs::create_dir_all(manpage_dir).expect("Unable to create directory for generated manpages"); + let app = Cli::command(); + let bin_name: &str = app + .get_bin_name() + .expect("Could not retrieve bin-name from generated Clap app"); + let app = Cli::command(); + let man = Man::new(app); + let mut buffer: Vec = Default::default(); + man.render(&mut buffer) + .expect("Unable to render man page to UTF-8 string"); + fs::write(manpage_dir.join(format!("{bin_name}.1")), buffer) + .expect("Unable to write manepage to file"); +} + +/// Generate shell completion files from CLI interface +#[cfg(feature = "completions")] +fn generate_shell_completions() { + let out_dir = match env::var_os("OUT_DIR") { + None => return, + Some(out_dir) => out_dir, + }; + let completions_dir = path::Path::new(&out_dir).join("completions"); + fs::create_dir_all(&completions_dir) + .expect("Could not create directory in which to place completions"); + let app = Cli::command(); + let bin_name: &str = app + .get_bin_name() + .expect("Could not retrieve bin-name from generated Clap app"); + let mut app = Cli::command(); + #[cfg(feature = "bash")] + generate_to(Bash, &mut app, bin_name, &completions_dir) + .expect("Unable to generate bash completions"); + #[cfg(feature = "elvish")] + generate_to(Elvish, &mut app, bin_name, &completions_dir) + .expect("Unable to generate elvish completions"); + #[cfg(feature = "fish")] + generate_to(Fish, &mut app, bin_name, &completions_dir) + .expect("Unable to generate fish completions"); + #[cfg(feature = "powershell")] + generate_to(PowerShell, &mut app, bin_name, &completions_dir) + .expect("Unable to generate powershell completions"); + #[cfg(feature = "zsh")] + generate_to(Zsh, &mut app, bin_name, &completions_dir) + .expect("Unable to generate zsh completions"); +} diff --git a/build-aux/cargo-updater.js b/build-aux/cargo-updater.js new file mode 100644 index 000000000..1b64fda44 --- /dev/null +++ b/build-aux/cargo-updater.js @@ -0,0 +1,12 @@ +const TOML = require('@iarna/toml') + +module.exports.readVersion = function (contents) { + const data = TOML.parse(contents) + return data.package.version +} + +module.exports.writeVersion = function (contents, version) { + const data = TOML.parse(contents) + data.package.version = version + return TOML.stringify(data) +} diff --git a/configure.ac b/configure.ac index 07fa850c0..aa873f85e 100644 --- a/configure.ac +++ b/configure.ac @@ -24,6 +24,12 @@ LT_INIT([dlopen]) AC_CANONICAL_HOST +AC_ARG_ENABLE(debug, + AS_HELP_STRING([--enable-debug],[Build Rust code with debugging information [default=no]]), + [debug_release=$enableval], + [debug_release=no]) +AM_CONDITIONAL([DEBUG_RELEASE], [test "x$debug_release" = "xyes"]) + AC_ARG_ENABLE([dependency-checks], AS_HELP_STRING([--disable-dependency-checks], [Disable dependency checks])) @@ -83,11 +89,13 @@ AM_COND_IF([DEPENDENCY_CHECKS], [ AX_FONT(Gentium Plus) + AX_PROGVAR([pdfinfo]) + AX_PROGVAR([jq]) + AX_PROGVAR([xargs]) AM_COND_IF([MANUAL], [ - AC_PATH_PROG([DOT], [dot]) - AC_PATH_PROG([GS], [gs]) + AX_PROGVAR([dot]) + AX_PROGVAR([gs]) ]) - AC_PATH_PROG([PDFINFO], [pdfinfo]) AC_MSG_CHECKING([for OS X]) have_appkit=no @@ -208,8 +216,64 @@ AM_COND_IF([DEPENDENCY_CHECKS], [ AX_PROGVAR([perl]) ]) + AX_PROGVAR([cargo]) + AX_PROGVAR([rustc]) + ]) +AC_MSG_CHECKING(whether to build Rust code with debugging information) +AM_COND_IF([DEBUG_RELEASE], [ + AC_MSG_RESULT(yes) + RUST_TARGET_SUBDIR=debug +], [ + AC_MSG_RESULT(no) + RUST_TARGET_SUBDIR=release +]) +AC_SUBST([RUST_TARGET_SUBDIR]) + +AC_ARG_WITH([bash-completion-dir], + AS_HELP_STRING([--with-bash-completion-dir[=PATH]], + [Install the bash auto-completion script in this directory. @<:@default=yes@:>@]), + [], + [with_bash_completion_dir=yes]) +if test "x$with_bash_completion_dir" = "xyes"; then + PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0], + [BASH_COMPLETION_DIR="`pkg-config --define-variable=datadir=$datadir --variable=completionsdir bash-completion`"], + [BASH_COMPLETION_DIR="$datadir/bash-completion/completions"]) + else + BASH_COMPLETION_DIR="$with_bash_completion_dir" +fi +AC_SUBST([BASH_COMPLETION_DIR]) +AM_CONDITIONAL([ENABLE_BASH_COMPLETION],[test "x$with_bash_completion_dir" != "xno"]) + +AC_ARG_WITH([fish-completion-dir], + AS_HELP_STRING([--with-fish-completion-dir[=PATH]], + [Install the fish auto-completion script in this directory. @<:@default=yes@:>@]), + [], + [with_fish_completion_dir=yes]) +if test "x$with_fish_completion_dir" = "xyes"; then + PKG_CHECK_MODULES([FISH_COMPLETION], [fish >= 3.0], + [FISH_COMPLETION_DIR="`pkg-config --define-variable=datadir=$datadir --variable=completionsdir fish`"], + [FISH_COMPLETION_DIR="$datadir/fish/vendor_completions.d"]) + else + FISH_COMPLETION_DIR="$with_fish_completion_dir" +fi +AC_SUBST([FISH_COMPLETION_DIR]) +AM_CONDITIONAL([ENABLE_FISH_COMPLETION],[test "x$with_fish_completion_dir" != "xno"]) + +AC_ARG_WITH([zsh-completion-dir], + AS_HELP_STRING([--with-zsh-completion-dir[=PATH]], + [Install the zsh auto-completion script in this directory. @<:@default=yes@:>@]), + [], + [with_zsh_completion_dir=yes]) +if test "x$with_zsh_completion_dir" = "xyes"; then + ZSH_COMPLETION_DIR="$datadir/zsh/site-functions" +else + ZSH_COMPLETION_DIR="$with_zsh_completion_dir" +fi +AC_SUBST([ZSH_COMPLETION_DIR]) +AM_CONDITIONAL([ENABLE_ZSH_COMPLETION],[test "x$with_zsh_completion_dir" != "xno"]) + AM_CONDITIONAL([APPKIT], [test "x$have_appkit" = "xyes"]) AM_CONDITIONAL([ICU], [test "x$with_icu" = "xyes"]) @@ -242,8 +306,15 @@ AC_SUBST([LUAROCKSARGS]) AX_SUBST_TRANSFORMED_PACKAGE_NAME -adl_RECURSIVE_EVAL(["${datadir}/${TRANSFORMED_PACKAGE_NAME}"], [SILE_PATH]) -AC_DEFINE_UNQUOTED([SILE_PATH],["${SILE_PATH}"],[Path for SILE packages and classes]) +# Avoid need for `--datarootdir=$(cd ..; pwd)` hack to run locally for +# tests/manual build when developer mode is enabled +AM_COND_IF([DEVELOPER], [ + AC_DEFINE_UNQUOTED([SILE_PATH],["$(pwd)"],[Path for SILE packages and classes]) + ],[ + adl_RECURSIVE_EVAL(["${datadir}/${TRANSFORMED_PACKAGE_NAME}"], [SILE_PATH]) + AC_DEFINE_UNQUOTED([SILE_PATH],["${SILE_PATH}"],[Path for SILE packages and classes]) +]) + AC_SUBST([SILE_PATH]) adl_RECURSIVE_EVAL(["${libdir}/${TRANSFORMED_PACKAGE_NAME}"], [SILE_LIB_PATH]) @@ -256,8 +327,8 @@ AC_SUBST([ROCKREV], [1]) AX_SUBST_MAN_DATE AC_CONFIG_FILES([build-aux/list-dist-files.sh], [chmod +x build-aux/list-dist-files.sh]) -AC_CONFIG_FILES([Makefile src/Makefile sile.1 core/features.lua core/pathsetup.lua core/version.lua]) -AC_CONFIG_FILES([sile tests/regressions.pl], [chmod +x sile tests/regressions.pl]) +AC_CONFIG_FILES([Makefile src/Makefile sile-lua.1 core/features.lua core/pathsetup.lua core/version.lua]) +AC_CONFIG_FILES([sile-lua:sile.in tests/regressions.pl], [chmod +x sile-lua tests/regressions.pl]) AC_CONFIG_FILES([sile-dev-1.rockspec:sile.rockspec.in]) AC_ARG_PROGRAM diff --git a/core/cli.lua b/core/cli.lua index 9f070dd55..884f0780d 100644 --- a/core/cli.lua +++ b/core/cli.lua @@ -2,8 +2,8 @@ local cli = pl.class() cli.parseArguments = function () local cliargs = require("cliargs") - local print_version = function() - print(SILE.full_version) + local print_version = function(flag) + print(flag == "V" and "SILE " .. SILE.version or SILE.full_version) os.exit(0) end cliargs:set_colsz(0, 120) @@ -32,7 +32,7 @@ cli.parseArguments = function () cliargs:flag("-q, --quiet", "suppress warnings and informational messages during processing") cliargs:flag("-t, --traceback", "display detailed location trace on errors and warnings") cliargs:flag("-h, --help", "display this help, then exit") - cliargs:flag("-v, --version", "display version information, then exit", print_version) + cliargs:flag("-V, --version", "display version information, then exit", print_version) -- Work around cliargs not processing - as an alias for STDIO streams: -- https://github.com/amireh/lua_cliargs/issues/67 local _arg = pl.tablex.imap(luautf8.gsub, _G.arg, "^-$", "STDIO") diff --git a/core/pathsetup.lua.in b/core/pathsetup.lua.in index ea9ad466f..b9ef4bc29 100644 --- a/core/pathsetup.lua.in +++ b/core/pathsetup.lua.in @@ -55,7 +55,7 @@ local pathvar = os.getenv("SILE_PATH") if pathvar then for path in string.gmatch(pathvar, "[^;]+") do if not path:match("^./") and path:len() >= 1 then - extendPaths(path) + extendPaths(path, true) end end end diff --git a/flake.nix b/flake.nix index ea0adc2ca..bc9023649 100644 --- a/flake.nix +++ b/flake.nix @@ -107,11 +107,20 @@ # Don't build the manual as it's time consuming, and it requires fonts # that are not available in the sandbox due to internet connection # missing. - configureFlags = pkgs.lib.lists.remove "--with-manual" oldAttr.configureFlags; + configureFlags = [ + "PDFINFO=false" + ] ++ ( + pkgs.lib.lists.remove "--with-manual" oldAttr.configureFlags + ); nativeBuildInputs = oldAttr.nativeBuildInputs ++ [ pkgs.autoreconfHook ]; buildInputs = [ + # Build inputs added since release in nixpkgs + pkgs.cargo + pkgs.jq + pkgs.rustc + ] ++ [ # Add here inputs needed for development, and not for Nixpkgs' build. pkgs.libarchive pkgs.perl diff --git a/package.json b/package.json index 3f6428a40..2cd7b2b73 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,10 @@ { "filename": "package.json", "type": "json" + }, + { + "filename": "Cargo.toml", + "updater": "build-aux/cargo-updater.js" } ], "infile": "CHANGELOG.md", diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 000000000..2bf5ad044 --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +stable diff --git a/sile.1.in b/sile-lua.1.in similarity index 100% rename from sile.1.in rename to sile-lua.1.in diff --git a/src/bin/sile.rs b/src/bin/sile.rs new file mode 100644 index 000000000..2df463373 --- /dev/null +++ b/src/bin/sile.rs @@ -0,0 +1,35 @@ +use clap::{CommandFactory, FromArgMatches}; + +use sile::cli::Cli; + +fn main() -> sile::Result<()> { + let version = option_env!("VERGEN_GIT_SEMVER").unwrap_or_else(|| env!("VERGEN_BUILD_SEMVER")); + let version = version.replacen('-', ".r", 1); + let long_version = sile::version()? + .strip_prefix("SILE ") + .unwrap_or("") + .to_string(); + let long_version = format!("{} [Rust]", long_version); + let app = Cli::command().version(version).long_version(long_version); + #[allow(unused_variables)] + let matches = app.get_matches(); + let args = Cli::from_arg_matches(&matches).expect("Unable to parse arguments"); + sile::run( + args.inputs, + args.backend, + args.class, + args.debug, + args.evaluate, + args.evaluate_after, + args.fontmanager, + args.makedeps, + args.output, + args.options, + args.preamble, + args.postamble, + args.r#use, + args.quiet, + args.traceback, + )?; + Ok(()) +} diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 000000000..758374113 --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,74 @@ +use clap::Parser; +use std::path::PathBuf; + +/// The SILE typesetter reads a single input file, by default in either SIL or XML format, and +/// processes it to generate a single output file, by default in PDF format. The output file will +/// be written to the same name as the input file with the extension changed to .pdf. Additional +/// input or output formats can be handled by requiring a module that adds support for them first. +#[derive(Parser, Debug)] +#[clap(author, name = "SILE", bin_name = "sile")] +pub struct Cli { + /// Input document, by default in SIL or XML format + pub inputs: Option>, + + /// Choose an alternative output backend + #[clap(short, long, value_name = "BACKEND")] + pub backend: Option, + + /// Override default document class + #[clap(short, long)] + pub class: Option, + + /// Show debug information for tagged aspects of SILE’s operation + #[clap(short, long, value_name = "DEBUGFLAG[,DEBUGFLAG]")] + // TODO: switch to num_args(0..) to allow space separated inputs + pub debug: Option>, + + /// Evaluate Lua expression before processing input + #[clap(short, long, value_name = "EXRPESION")] + pub evaluate: Option>, + + /// Evaluate Lua expression after processing input + #[clap(short = 'E', long, value_name = "EXRPESION")] + pub evaluate_after: Option>, + + /// Choose an alternative font manager + #[clap(short, long, value_name = "FONTMANAGER")] + pub fontmanager: Option, + + /// Generate a list of dependencies in Makefile format + #[clap(short, long, value_name = "FILE")] + pub makedeps: Option, + + /// Explicitly set output file name + #[clap(short, long, value_name = "FILE")] + pub output: Option, + + /// Set document class options + #[clap(short = 'O', long)] + pub options: Option>, + + /// Process SIL, XML, or other content before the input document + #[clap(short, long, value_name = "FILE")] + pub preamble: Option>, + + /// Process SIL, XML, or other content after the input document + #[clap(short = 'P', long, value_name = "FILE")] + pub postamble: Option>, + + /// Load and initialize a module before processing input + #[clap( + short, + long, + value_name = "MODULE[[PARAMETER=VALUE[,PARAMETER=VALUE]]]" + )] + pub r#use: Option>, + + /// Discard all non-error output messages + #[clap(short, long)] + pub quiet: bool, + + /// Display detailed location trace on errors and warnings + #[clap(short, long)] + pub traceback: bool, +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 000000000..f1e53ed11 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,159 @@ +use lazy_static::lazy_static; +use mlua::chunk; +use mlua::prelude::*; +use std::path::PathBuf; +#[cfg(feature = "cli")] +pub mod cli; + +pub type Result = anyhow::Result; + +// These env vars are generated by autoconf *at compile time* in order to emulate the system +// default Lua interpreter. If they exist we use them, else keep it to ourselves. +lazy_static! { + #[derive(Debug)] + pub static ref LUA_PATH: &'static str = option_env!["LUA_PATH"].unwrap_or_else(|| "./?.lua"); + #[derive(Debug)] + pub static ref LUA_CPATH: &'static str = option_env!["LUA_CPATH"].unwrap_or_else(|| ""); +} + +pub fn version() -> crate::Result { + let lua = unsafe { Lua::unsafe_new() }; + let lua_path: LuaString = lua.create_string(&LUA_PATH.clone())?; + let lua_cpath: LuaString = lua.create_string(&LUA_CPATH.clone())?; + let sile_path: LuaString = lua.create_string(env!("SILE_PATH"))?; + let sile: LuaTable = lua + .load(chunk! { + package.path = $lua_path + package.cpath = $lua_cpath + local status = pcall(dofile, $sile_path .. "/core/pathsetup.lua") + if not status then + dofile("./core/pathsetup.lua") + end + return require("core.sile") + }) + .eval()?; + Ok(sile.get("full_version")?) +} + +// Yes I know this should be taking a struct, probably 1 with what ends up being SILE.input and one +// with other stuff the CLI may inject, but I'm playing with what a minimum/maximum set of +// parameters would look like here while maintaining compatiblitiy with the Lua CLI. +#[allow(clippy::too_many_arguments)] +pub fn run( + inputs: Option>, + backend: Option, + class: Option, + debug: Option>, + evaluate: Option>, + evaluate_after: Option>, + fontmanager: Option, + makedeps: Option, + output: Option, + options: Option>, + preamble: Option>, + postamble: Option>, + r#use: Option>, + quiet: bool, + traceback: bool, +) -> crate::Result<()> { + let lua = unsafe { Lua::unsafe_new() }; + let lua_path: LuaString = lua.create_string(&LUA_PATH.clone()).unwrap(); + let lua_cpath: LuaString = lua.create_string(&LUA_CPATH.clone()).unwrap(); + let sile_path: LuaString = lua.create_string(env!("SILE_PATH"))?; + let sile: LuaTable = lua + .load(chunk! { + package.path = $lua_path + package.cpath = $lua_cpath + local status = pcall(dofile, $sile_path .. "/core/pathsetup.lua") + if not status then + dofile("./core/pathsetup.lua") + end + return require("core.sile") + }) + .eval()?; + sile.set("traceback", traceback)?; + sile.set("quiet", quiet)?; + let mut has_input_filename = false; + if let Some(flags) = debug { + let debug_flags: LuaTable = sile.get("debugFlags")?; + for flag in flags { + debug_flags.set(flag, true)?; + } + } + let full_version: String = sile.get("full_version")?; + let sile_input: LuaTable = sile.get("input")?; + if let Some(expressions) = evaluate { + sile_input.set("evaluates", expressions)?; + } + if let Some(expressions) = evaluate_after { + sile_input.set("evaluateAfters", expressions)?; + } + if let Some(backend) = backend { + sile.set("backend", backend)?; + } + if let Some(fontmanager) = fontmanager { + sile.set("fontmanager", fontmanager)?; + } + if let Some(class) = class { + sile_input.set("class", class)?; + } + if let Some(paths) = preamble { + sile_input.set("preambles", paths_to_strings(paths))?; + } + if let Some(paths) = postamble { + sile_input.set("postamble", paths_to_strings(paths))?; + } + if let Some(path) = makedeps { + sile_input.set("makedeps", path_to_string(&path))?; + } + if let Some(path) = output { + sile.set("outputFilename", path_to_string(&path))?; + has_input_filename = true; + } + if let Some(options) = options { + sile_input.set("options", options)?; + } + if let Some(modules) = r#use { + sile_input.set("use", modules)?; + } + if !quiet { + eprintln!("{full_version} [Rust]"); + } + let init: LuaFunction = sile.get("init")?; + init.call::<_, _>(())?; + if let Some(inputs) = inputs { + let input_filenames: LuaTable = lua.create_table()?; + for input in inputs.iter() { + let path = &path_to_string(input); + if !has_input_filename && path != "-" { + has_input_filename = true; + } + input_filenames.push(lua.create_string(path)?)?; + } + if !has_input_filename { + panic!( + "\nUnable to derive an output filename (perhaps because input is a STDIO stream)\nPlease use --output to set one explicitly." + ); + } + sile_input.set("filenames", input_filenames)?; + let input_filenames: LuaTable = sile_input.get("filenames")?; + let process_file: LuaFunction = sile.get("processFile")?; + for file in input_filenames.sequence_values::() { + process_file.call::(file?)?; + } + let finish: LuaFunction = sile.get("finish")?; + finish.call::<_, _>(())?; + } else { + let repl: LuaTable = sile.get("repl")?; + repl.call_method::<_, _, _>("enter", ())?; + } + Ok(()) +} + +fn path_to_string(path: &PathBuf) -> String { + path.clone().into_os_string().into_string().unwrap() +} + +fn paths_to_strings(paths: Vec) -> Vec { + paths.iter().map(path_to_string).collect() +}