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}