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