trail/
lib.rs

1//! Build cross-platform paths at compile time.
2//!
3//! ## Installation
4//!
5//! First, add [`trail`] to the dependencies section of your `Cargo.toml`:
6//!
7//! ```toml
8//! [dependencies]
9//! trail = "0.1"
10//! ```
11//!
12//! Next, add the following snippet to the entry point of your crate (`lib.rs` or `main.rs`):
13//!
14//! ```rust
15//! #[macro_use]
16//! extern crate trail;
17//! #
18//! # fn main() {}
19//! ```
20//!
21//! ## Usage
22//!
23//! You can also use [`trail!`] anywhere else an expression is expected. The expanded output
24//! is functionally equivelant to calling [`Path::new`] with a hard coded literal.
25//!
26//! ```rust
27//! # #[macro_use]
28//! # extern crate trail;
29//! #
30//! # use std::path::Path;
31//! #
32//! # fn main() {
33//! let absolute = &trail!("", "hello", "world");
34//! let relative = &trail!("hello", "world");
35//!
36//! if cfg!(windows) {
37//!     assert_eq!(*absolute, Path::new("\\hello\\world"));
38//!     assert_eq!(*relative, Path::new("hello\\world"));
39//! } else {
40//!     assert_eq!(*absolute, Path::new("/hello/world"));
41//!     assert_eq!(*relative, Path::new("hello/world"));
42//! }
43//! # }
44//! ```
45//!
46//! [`trail!`]: ./macro.trail.html
47//! [`trail`]: https://crates.io/crates/trail
48//!
49//! [`Path`]: https://doc.rust-lang.org/std/path/struct.Path.html
50//! [`Path::new`]: https://doc.rust-lang.org/std/path/struct.Path.html#method.new
51
52#![cfg_attr(feature = "clippy", feature(plugin))]
53#![cfg_attr(feature = "clippy", plugin(clippy))]
54
55/// A macro for building a cross-platform [`Path`] at compile time.
56///
57/// ## Example
58///
59/// ```rust
60/// # #[macro_use]
61/// # extern crate trail;
62/// #
63/// # use std::path::Path;
64/// #
65/// # fn main() {
66/// let absolute = &trail!("", "hello", "world");
67/// let relative = &trail!("hello", "world");
68///
69/// if cfg!(windows) {
70///     assert_eq!(*absolute, Path::new("\\hello\\world"));
71///     assert_eq!(*relative, Path::new("hello\\world"));
72/// } else {
73///     assert_eq!(*absolute, Path::new("/hello/world"));
74///     assert_eq!(*relative, Path::new("hello/world"));
75/// }
76/// # }
77/// ```
78///
79/// [`Path`]: https://doc.rust-lang.org/std/path/struct.Path.html
80#[macro_export]
81macro_rules! trail {
82    ( $($segment:expr),* ) => ( ::std::path::Path::new(__trail!($($segment),*)) );
83}
84
85#[doc(hidden)]
86#[cfg(not(windows))]
87#[macro_export]
88macro_rules! __trail {
89    () => ( "" );
90    ( $base:expr ) => ( $base );
91    ( $base:expr, $($segment:expr),+ ) => ( concat!($base, $("/", $segment),+) );
92}
93
94#[doc(hidden)]
95#[cfg(windows)]
96#[macro_export]
97macro_rules! __trail {
98    () => ( "" );
99    ( $base:expr ) => ( $base );
100    ( $base:expr, $($segment:expr),+ ) => ( concat!($base, $("\\", $segment),+) );
101}
102
103#[cfg(test)]
104mod tests {
105    use std::path::Path;
106
107    #[test]
108    fn trail() {
109        if cfg!(windows) {
110            assert_eq!(trail!(), Path::new(""));
111            assert_eq!(trail!(""), Path::new(""));
112            assert_eq!(trail!("hello"), Path::new("hello"));
113            assert_eq!(trail!("hello", "world"), Path::new("hello\\world"));
114            assert_eq!(trail!("", "hello", "world"), Path::new("\\hello\\world"));
115        } else {
116            assert_eq!(trail!(), Path::new(""));
117            assert_eq!(trail!(""), Path::new(""));
118            assert_eq!(trail!("hello"), Path::new("hello"));
119            assert_eq!(trail!("hello", "world"), Path::new("hello/world"));
120            assert_eq!(trail!("", "hello", "world"), Path::new("/hello/world"));
121        }
122    }
123}