cargo-equip

CI codecov unsafe forbidden Crates.io Crates.io

English

競技プログラミング用にRustコードを一つの.rsファイルにバンドルするCargoサブコマンドです。

例

Point Add Range Sum - Library-Cheker

lib側

toml [package.metadata.cargo-equip-lib.mod-dependencies] "algebraic" = [] "fenwick" = ["algebraic"] "input" = [] "output" = []

bin側

toml [dependencies] __complib = { package = "complib", path = "/path/to/complib" } cargo_equip_marker = { git = "https://github.com/qryxip/cargo-equip", rev = "37d4972d57be0d41d3d8edfb5db691487359cb3b" }

```rust

[cargo_equip::equip]

use ::__complib::{fenwick::AdditiveFenwickTree, input, output};

use std::io::Write as _;

fn main() { input! { n: usize, q: usize, r#as: [i64; n], }

let mut bit = AdditiveFenwickTree::new(n);

for (i, a) in r#as.into_iter().enumerate() {
    bit.plus(i, &a);
}

output::buf_print(|out| {
    macro_rules! println(($($tt:tt)*) => (std::writeln!(out, $($tt)*).unwrap()));
    for _ in 0..q {
        input!(kind: u32);
        match kind {
            0 => {
                input!(p: usize, x: i64);
                bit.plus(p, &x);
            }
            1 => {
                input!(l: usize, r: usize);
                println!("{}", bit.query(l..r));
            }
            _ => unreachable!(),
        }
    }
});

} ```

↓

console $ cargo equip --oneline mods --rustfmt --check | xsel -ib Bundling code Checking cargo-equip-check-output-ixtp05p7mhbiumzg v0.1.0 (/tmp/cargo-equip-check-output-ixtp05p7mhbiumzg) Finished dev [unoptimized + debuginfo] target(s) in 0.21s

https://judge.yosupo.jp/submission/20767

インストール

Crates.io

console $ cargo install cargo-equip

master

console $ cargo install --git https://github.com/qryxip/cargo-equip

GitHub Releases

バイナリでの提供もしています。

使い方

まずライブラリをこのように横に広く作ってください。 深さ2以上のモジュールはinline module (mod { .. })として書いてください。

src ├── a.rs ├── b.rs ├── c.rs └── lib.rs

rust // src/lib.rs pub mod a; pub mod b; pub mod c;

次にライブラリのCargo.tomlのpackage.metadataにモジュールの依存関係を手で書いてください。 欠けている場合はwarningと共にすべてのモジュールを展開します。

使う側で指定できるようにすることも考えています。

toml [package.metadata.cargo-equip-lib.mod-dependencies] "a" = [] "b" = ["a"] "c" = ["a"]

bin側の準備としては、次の2つをdependenciesに加えてください。

toml [dependencies] __my_lib = { package = "my_lib", path = "/path/to/my_lib" } cargo_equip_marker = { git = "https://github.com/qryxip/cargo-equip", rev = "37d4972d57be0d41d3d8edfb5db691487359cb3b" }

ライブラリは誤って直接使わないようにリネームしておくことを強く推奨します。

cargo_equip_markerは何もしないattribute macroである#[equip]を提供します。 cargo-snippetのやりかたを真似たものですが、本ツールでは別のパッケージに分けています。 cargo-equipと間違えないようにしてください。 cargo_equip_markerから#[::cargo_equip::equip]として呼びます。

準備ができたらこのようにライブラリをuseします。

```rust

[cargo_equip::equip]

use ::_mylib::{b::B, c::C}; ```

useのパスにはleading colon (::)を付けてください。

```

[cargo_equip::equip]

use ::_mylib::{b::B, c::C}; ^^ ```

パスの1つ目のsegmentから展開するべきライブラリを決定します。 leading colonを必須としているのはこのためです。

```

[cargo_equip::equip]

use ::_mylib::{b::B, c::C}; ^^^^^^^^ ```

パスの2つ目のsegmentから使用しているモジュールを判定します。 これらのモジュールと、先程書いたmod-dependenciesで繋がっているモジュールが展開されます。

```

[cargo_equip::equip]

use ::_mylib::{b::B, c::C}; ^ ^ ```

パスの3つ目以降のsegmentはuse self::$name::{ .. }として展開されます。

```

[cargo_equip::equip]

use ::_mylib::{b::B, c::C}; ^ ^ ```

コードが書けたらcargo equipで展開します。 --bin {binの名前}か--src {binのファイルパス}でbinを指定してください。 パッケージ内のbinが一つの場合は省略できます。 ただしdefault-runには未対応です。

console $ cargo equip --bin "$name"

コードはこのように展開されます。

```rust /#[cargo_equip::equip] use ::__my_lib::{b::B, c::C};/

fn main() { todo!(); }

// The following code was expanded by cargo-equip.

use self::b::B; use self::c::C;

// bとcで使われているとmod-dependenciesに記述されているため、展開される mod a { // .. }

mod b { // .. }

mod c { // .. } ```

モジュールの階層が変わらないため、各ファイルの中身を手を加えずにそのまま展開します。 そのため壊れにくくなっているはずです。 多分。

またライブラリ内の#[macro_export]しているマクロですが、マクロ名と同名のモジュールに入れておくと自然な形で使えると思います。

```rust // input.rs

[macro_export]

macrorules! input { ($($tt:tt)*) => { compileerror!("TODO") }; } ```

```rust

[cargo_equip::equip]

use ::_mylib::input; ```

オプション

--oneline

--oneline modsで展開後の各モジュールをそれぞれ一行に折り畳みます。 --oneline allでコード全体を一行に折り畳みます。

トークン列を" "区切りで出力しているだけなので、minificationではありません。

--rustfmt

出力をRustfmtでフォーマットします。

--check

バンドルしたコードを出力する前にtarget directoryを共有した一時パッケージを作り、それの上でcargo checkします。

console $ cargo equip --check > /dev/null Bundling code Checking cargo-equip-check-output-6oxyyu9lsf9s0f6g v0.1.0 (/tmp/cargo-equip-check-output-6oxyyu9lsf9s0f6g) Finished dev [unoptimized + debuginfo] target(s) in 0.18s

ライセンス

MIT or Apache-2.0のデュアルライセンスです。