Giter VIP home page Giter VIP logo

dirmod's Introduction

dirmod

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

Tired of writing and updating all the mod statements in mod.rs? Generate them with dirmod instead.

dirmod scans your directory and generates the corresponding mod statements automatically with a simple macro call:

dirmod::all!();

And that's all!

(Note: dirmod is designed for Rust 2018 Edition, so macros take simple and ambiguous names like all, os, etc. It is recommended to call the macros in fully-qualified fashion like dirmod::all!(), dirmod::os!(), etc. for clarity. The old #[macro_use] extern crate dirmod; style is not recommended.)

Visibility

Default visibility

All modules can be set to a common visibility, e.g. pub mod or pub(self) mod, etc. at your favour:

dirmod::all!(default pub);

Re-exporting

You can also make all modules private, and set the visibility for the re-exported items instead:

dirmod::all!(default pub use);

Separate file defaults and directory defaults

It might be common to handle file modules and directory modules separately:

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

This re-exports all items from file modules, and makes all directory modules public by name. (This behaviour is similar to the package system in Go)

The default behaviour

If the default argument is not given, default file priv use; default dir priv is the default choice.

Individual visibility

If there are individual modules among dozens that need special visibility configuration, it is also possible to write:

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

Then all modules have pub visibility, except foo and bar which are private.

Similarly, if all modules are publicly re-exported and foo and bar are only exported as modules:

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

Conditional compilation

But I use mod to implement conditional compilation!

No problem, dirmod generates cfg attributes for some idiomatic styles:

  • A directory where each module name is the feature name (e.g. #[cfg(feature = "foo")] mod foo;)
  • A directory where each module name is the OS/OS family name (e.g. #[cfg(target_family = "unix")] mod unix;)

This can be achieved by calling dirmod::os!(), dirmod::family!() or dirmod::feature!().

It is likely that different OS variants of the same module expose the same API, so it might be practical to write:

dirmod::os!(pub use);

If none of the modules support the current OS, you could trigger a compile error:

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

Or with a custom error message:

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

Note that it does not make sense to use the || on dirmod::feature!, because Cargo features are incremental and should not be restricted in amount.

File an issue if I missed any common styles!

But I am still unhappy about xxxx corner case!

No problem, you don't have to use dirmod for every module. dirmod::all!() has an except argument that excludes certain modules. Since the macro simply generates mod statements, it is perfectly fine to add more items before/after the macro call.

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

Documentation

Instead of writing docs in mod.rs, write them in the module directly. In addition to dirmod constraints, there are a few advantages:

  • Avoid lots of docs mixed together in a single mod.rs. Easier to navigate!
  • Writing docs inside the module itself is much more relevant than references to the parent module.

To write docs for the module, use this syntax at the top of the module (before any other items):

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

Supported Rust versions

Since detecting the source file requires the proc_macro_span feature, Rust Nightly is required to compile this crate.

Examples

See the testcrate directory, which demonstrates the use of dirmod::all! and dirmod::family!.

Syntax reference

A BNF syntax reference is available at syntax.bnf.

Known unresolved issues

rustfmt support

rustfmt and cargo fmt operate on the modules directly included by the entry points by detecting direct mod statements in the included files. Since rustfmt does not expand (or even compile) macros (known issue), modules included by dirmod would not be formatted.

The most straightforward alternative for now is to run rustfmt src/**/*.rs with shopt -s globstar enabled on a Linux shell.

Error reporting

The Rust compiler may fail to locate syntax error locations correctly (known issue). However, this issue has only been reproduced with the specific case where the syntax error is related to leading #[] which could be an inner attribute.

dirmod's People

Contributors

dependabot-preview[bot] avatar sof3 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

jkelleyrtp

dirmod's Issues

Conditional compilation by suffix

The current dirmod::os!() macro requires a structure like this:

- mod.rs - includes foo, bar, qux
- foo.rs
- bar.rs
- qux/
  - qux/mod.rs - dirmod::os!()
  - qux/windows.rs
  - qux/unix.rs

It might be preferrable to have a structure like this:

- mod.rs - includes foo, bar, qux
- foo.rs
- bar.rs
- qux_windows.rs
- qux_unix.rs

This can be activated by providing a flag like with family suffix; in the dirmod::all!() call in mod.rs.

If qux.rs is also present, there are two possible solutions:

  • trigger a compile error
  • declare a module like this:
$vis mod qux {
  #[path = "qux.rs"] mod _common;
  pub use _common::*;

  #[cfg(target_family = "windows")] #[path = "qux_windows.rs"] mod _windows;
  pub use _windows::*;

  #[cfg(target_family = "unix")] #[path = "qux_unix.rs"] mod _unix;
  pub use _unix::*;
}

The former is preferred as it leads to less confusion. In particular, the latter solution might be confusing in that the exports from qux_windows.rs and qux_unix.rs actually cannot be used in qux.rs.

Separate default for file and directory modules

Users might want to handle all files or all directories differently.

Possible syntax:

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

This makes all file modules pub mod x; by default, and all directory modules mod x; pub use x; by default.

Trivia: The example syntax above leads to behaviour similar to that in Go.

Dependabot can't resolve your Rust dependency files

Dependabot can't resolve your Rust dependency files.

As a result, Dependabot couldn't update your dependencies.

The error Dependabot encountered was:

error: failed to parse manifest at `/home/dependabot/dependabot-updater/dependabot_tmp_dir/Cargo.toml`

Caused by:
  readme file with name 'README.md' was not found

If you think the above is an error on Dependabot's side please don't hesitate to get in touch - we'll do whatever we can to fix it.

View the update logs.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.