|
16 | 16 | //! |
17 | 17 | //! * macos => default, as well as browsers listed under [Browser](enum.Browser.html) |
18 | 18 | //! * windows => default browser only |
19 | | -//! * linux => default browser only (uses $BROWSER env var, failing back to xdg-open) |
| 19 | +//! * linux => default browser only (uses $BROWSER env var, failing back to xdg-open, gvfs-open and |
| 20 | +//! gnome-open, in that order) |
20 | 21 | //! * android => not supported right now |
21 | 22 | //! * ios => not supported right now |
22 | 23 | //! |
@@ -110,19 +111,50 @@ fn open_on_windows(browser: Browser, url: &str) -> Result<Output> { |
110 | 111 | } |
111 | 112 | } |
112 | 113 |
|
113 | | -/// Deal with opening of browsers on Linux, using `xdg-open` command |
| 114 | +/// Deal with opening of browsers on Linux - currently supports only the default browser |
| 115 | +/// |
| 116 | +/// The mechanism of opening the default browser is as follows: |
| 117 | +/// 1. Attempt to use $BROWSER env var if available |
| 118 | +/// 2. Attempt to open the url via xdg-open, gvfs-open, gnome-open, respectively, whichever works |
| 119 | +/// first |
114 | 120 | fn open_on_linux(browser: Browser, url: &str) -> Result<Output> { |
115 | 121 | match browser { |
116 | | - Browser::Default => Command::new(env::var("BROWSER").or::<Result<String>>(Ok("xdg-open".to_string())).unwrap()) |
117 | | - .arg(url) |
118 | | - .output(), |
| 122 | + Browser::Default => open_on_linux_using_browser_env(url) |
| 123 | + .or_else(|_| -> Result<Output> {Command::new("xdg-open").arg(url).output()}) |
| 124 | + .or_else(|_| -> Result<Output> {Command::new("gvfs-open").arg(url).output()}) |
| 125 | + .or_else(|_| -> Result<Output> {Command::new("gnome-open").arg(url).output()}), |
119 | 126 | _ => Err(Error::new( |
120 | 127 | ErrorKind::NotFound, |
121 | 128 | "Only the default browser is supported on this platform right now" |
122 | 129 | )) |
123 | 130 | } |
124 | 131 | } |
125 | 132 |
|
| 133 | +/// Open on Linux using the $BROWSER env var |
| 134 | +fn open_on_linux_using_browser_env(url: &str) -> Result<Output> { |
| 135 | + let browsers = try!(env::var("BROWSER").map_err(|_| -> Error {Error::new(ErrorKind::NotFound, format!("BROWSER env not set"))})); |
| 136 | + for browser in browsers.split(':') { // $BROWSER can contain ':' delimited options, each representing a potential browser command line |
| 137 | + if !browser.is_empty() { |
| 138 | + // each browser command can have %s to represent URL, while %c needs to be replaced |
| 139 | + // with ':' and %% with '%' |
| 140 | + let cmdline = browser.replace("%s", url).replace("%c", ":").replace("%%", "%"); |
| 141 | + let cmdarr: Vec<&str> = cmdline.split_whitespace().collect(); |
| 142 | + let mut cmd = Command::new(&cmdarr[0]); |
| 143 | + if cmdarr.len() > 1 { |
| 144 | + cmd.args(&cmdarr[1..cmdarr.len()]); |
| 145 | + } |
| 146 | + if !browser.contains("%s") { |
| 147 | + // append the url as an argument only if it was not already set via %s |
| 148 | + cmd.arg(url); |
| 149 | + } |
| 150 | + if let Ok(output) = cmd.output() { |
| 151 | + return Ok(output); |
| 152 | + } |
| 153 | + } |
| 154 | + } |
| 155 | + return Err(Error::new(ErrorKind::NotFound, "No valid command in $BROWSER")); |
| 156 | +} |
| 157 | + |
126 | 158 | #[test] |
127 | 159 | fn test_open_default() { |
128 | 160 | assert!(open("http://github.com").is_ok()); |
|
0 commit comments