2 个不稳定版本

0.2.0-alpha.12019年11月22日
0.1.4 2019年10月21日

#16 in #conditional-compilation


3 个 crate 中使用 (通过 dirmod)

Apache-2.0

34KB
665

dirmod

Travis-CI crates.io crates.io docs.rs GitHub

厌倦了在 mod.rs 中编写和更新所有的 mod 语句吗?用 dirmod 来生成它们。

dirmod 会扫描你的目录,并通过简单的宏调用自动生成相应的 mod 语句

dirmod::all!();

就这样!

(注意:dirmod是为Rust 2018 版本设计的,因此宏采用简单且模糊的名称,如allos等。建议使用完全限定名称来调用宏,例如dirmod::all!()dirmod::os!()等,以提高清晰度。不建议使用旧的#[macro_use] extern crate dirmod;样式。)

可见性

默认可见性

所有模块都可以设置为一个共同的可见性,例如pub modpub(self) mod等,任君选择

dirmod::all!(default pub);

重新导出

您也可以将所有模块设置为私有,并为重新导出的项目设置可见性

dirmod::all!(default pub use);

单独文件默认值和目录默认值

可能需要分别处理文件模块和目录模块

dirmod::all!(default file pub use; default dir pub);

这将重新导出文件模块中的所有项目,并按名称将所有目录模块设置为公开。(此行为类似于 Go 的包系统)

默认行为

如果没有提供default参数,则默认选择是default file priv use; default dir priv

单独的可见性

如果有几十个模块中需要特殊可见性配置的单独模块,也可以这样写

dirmod::all!(default pub; priv foo, bar);

然后所有模块都具有pub可见性,除了foobar是私有的。

同样,如果所有模块都是公开重新导出,且foobar仅作为模块导出

dirmod::all!(default pub use; pub foo, bar);

条件编译

但我使用mod来实现条件编译!

没问题,dirmod为某些惯用风格生成cfg属性。

  • 一个目录,每个模块名称是功能名称(例如:#[cfg(feature = "foo")] mod foo;)
  • 一个目录,每个模块名称是操作系统/操作系统家族名称(例如:#[cfg(target_family = "unix")] mod unix;)

可以通过调用dirmod::os!()dirmod::family!()dirmod::feature!()来实现。

同一个模块的不同操作系统变体可能暴露相同的API,因此可能有必要编写

dirmod::os!(pub use);

如果没有模块支持当前操作系统,则可以触发编译错误

dirmod::os!(pub use ||);

或者使用自定义错误信息

dirmod::os!(pub use || "custom error message");

注意,在dirmod::feature!上使用||没有意义,因为Cargo功能是增量式的,不应限制数量。

如果遗漏了任何常见风格,请提交问题

但我对xxxx特殊情况仍然不满意!

没问题,你不必为每个模块使用dirmoddirmod::all!()有一个except参数,可以排除某些模块。由于宏仅仅生成mod语句,所以在宏调用前后添加更多项是完全可行的。

dirmod::all!(except corge, grault);

文档

直接在模块中编写文档,而不是在mod.rs中编写。除了dirmod约束外,还有一些优点

  • 避免在单个mod.rs中将大量文档混合在一起。更容易导航!
  • 在模块内部编写文档比引用父模块更为相关。

要编写模块的文档,请在模块顶部使用此语法(在所有其他项之前)

//! Yay, I'm now describing myself!
//! I finally have my own place!

支持的Rust版本

由于检测源文件需要proc_macro_span特性,因此需要Rust Nightly来编译此crate。

示例

请参阅testcrate目录,该目录演示了dirmod::all!dirmod::family!的使用。

语法参考

BNF语法参考可在syntax.bnf找到。

已知未解决的问题

rustfmt支持

rustfmtcargo fmt直接在入口点包含的模块上操作,通过检测包含文件中的直接mod语句。由于rustfmt不会展开(甚至编译)宏(已知问题),因此由dirmod包含的模块不会被格式化。

目前最直接的方法是在Linux shell上启用shopt -s globstar的情况下运行rustfmt src/**/*.rs

错误报告

Rust编译器可能无法正确定位语法错误位置(已知问题)。然而,这个问题仅在语法错误与相关的内联属性(可能是前导的#[])相关的特定情况下重现。

依赖关系

~1.5MB
~37K SLoC