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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
// region: auto_md_to_doc_comments include README.md A //!
//! # wsl_open_browser
//!
//! **Inside WSL2 opens a html file in the browser that is in Win10. The local file path is transformed between Linux and Win10 notation.**  
//! ***[repository](https://github.com/LucianoBestia/wsl_open_browser); version: 2021.823.702  date: 2021-08-23 authors: Luciano Bestia***  
//!
//! [![Lines in Rust code](https://img.shields.io/badge/Lines_in_Rust-45-green.svg)](https://github.com/LucianoBestia/wsl_open_browser/)
//! [![Lines in Doc comments](https://img.shields.io/badge/Lines_in_Doc_comments-150-blue.svg)](https://github.com/LucianoBestia/wsl_open_browser/)
//! [![Lines in Comments](https://img.shields.io/badge/Lines_in_comments-15-purple.svg)](https://github.com/LucianoBestia/wsl_open_browser/)
//! [![Lines in examples](https://img.shields.io/badge/Lines_in_examples-0-yellow.svg)](https://github.com/LucianoBestia/wsl_open_browser/)
//! [![Lines in tests](https://img.shields.io/badge/Lines_in_tests-0-orange.svg)](https://github.com/LucianoBestia/wsl_open_browser/)
//!
//! [![crates.io](https://img.shields.io/crates/v/cargo-auto.svg)](https://crates.io/crates/wsl_open_browser) [![Documentation](https://docs.rs/wsl_open_browser/badge.svg)](https://docs.rs/wsl_open_browser/) [![crev reviews](https://web.crev.dev/rust-reviews/badge/crev_count/wsl_open_browser.svg)](https://web.crev.dev/rust-reviews/crate/wsl_open_browser/) [![Lib.rs](https://img.shields.io/badge/Lib.rs-rust-orange.svg)](https://lib.rs/crates/wsl_open_browser/) [![Licence](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/LucianoBestia/wsl_open_browser/blob/master/LICENSE) [![Rust](https://github.com/LucianoBestia/wsl_open_browser/workflows/RustAction/badge.svg)](https://github.com/LucianoBestia/wsl_open_browser/)   
//!
//! ## Try it
//!
//! Install it from crates.io and add 2 symbolic links and one env variable:
//!
//! ```bash
//! cargo install wsl_open_browser
//! sudo ln -sf "/mnt/c/Program Files/Mozilla Firefox/firefox.exe" /usr/bin/browser_in_win
//! export BROWSER='/usr/bin/wsl_open_browser'
//! # I like to use the short command `www` to open a browser
//! ln -sf "/usr/bin/wsl_open_browser" www
//!
//! # go to a directory that contains a subdirectory with index.html
//! cd ~/rustprojects/wsl_open_browser
//! www docs/index.html
//! # or
//! www docs
//! # or go inside the directory that contains index.html
//! cd docs
//! www .
//! # or simply
//! www
//! # if you want to open an URL
//! www rust-lang.org
//! ```
//!
//! Congratulations! You have just opened a windows browser from WSL2.
//!
//! ## Motivation
//!
//! Inside WSL2 I want to open a html file in the browser. But the browser is in Win10.  
//! This is useful in Rust for the documentation:
//!
//! ```bash
//! cargo doc --open
//! ```
//!
//! or for simply open a file in a browser from bash:
//!
//! ```bash
//! www index.html
//! ```
//!
//! ## Open URL in Win10 Browser (first attempt)
//!
//! I prepared a symbolic link to the firefox exe.
//!
//! ```bash
//! ln -s "/mnt/c/Program Files/Mozilla Firefox/firefox.exe" /usr/bin/browser_in_win
//! # now I can open a page like this
//! browser_in_win http://github.com
//! # I want to open it with xdg-open
//! # xdg-open is the "Open any file" for linux
//! export BROWSER='/usr/bin/browser_in_win'
//! # now I can use
//! xdg-open http://rust-lang.org
//! ```
//!
//! This works great for URL, but it does not work for local files, because Linux and Windows see the same file with different paths.  
//! The command `ln -sf` is permanent and persistent. It makes a file that stays there forever.  
//! But `export BROWSER=` is NOT persistent. You need to add this command to `~/.bashrc` that runs it on every start of terminal.  
//!
//! ## Open local file in Win10 Browser
//!
//! For example:  
//! Linux: `/home/luciano/index.html`  
//! Win10: `\\wsl$\Debian\home\luciano\index.html`  
//! OR:  
//! Linux: `/mnt/c/Users/Luciano/Downloads\index.html`  
//! Win10: `c:\Users\Luciano\Downloads\index.html`  
//!
//! I need a way to transform the path prior to call the browser.  
//! Let's make a Rust CLI for that.
//!
//! ## Development
//!
//! This is a simple binary. For good habit I separated the lib from the bin.  
//! Use [cargo auto](https://crates.io/crates/cargo-auto) to run automation tasks: build, release, doc, copy_to_usr_bin,....  
//! After `cargo auto copy_to_usr_bin` we can now open the browser like this:  
//!
//! ```bash
//! wsl_open_browser http://rust-lang.org
//! wsl_open_browser /home/luciano/index.html
//! wsl_open_browser /mnt/c/Users/Luciano/Downloads/index.html
//! wsl_open_browser docs/index.html
//! ```
//!
//! ## Open with xdg-open
//!
//! But I want to use xdg-open.  
//! xdg-open is the "Open any file" for linux.  
//! For that I need to set the environment variable BROWSER.  
//! To make it persistent, copy this line to `~/.bashrc`.
//!
//! ```bash
//! export BROWSER='/usr/bin/wsl_open_browser'
//! ```
//!
//! Finally we can open the browser like this:
//!
//! ```bash
//! xdg-open http://rust-lang.org
//! xdg-open /home/luciano/index.html
//! xdg-open /mnt/c/Users/Luciano/Downloads/index.html
//! ```
//!
//! and the Rust documentation works fine:
//!
//! ```bash
//! cargo doc --open
//! ```
//!
//! ## simply: `www docs` or `www .`
//!
//! I am still not satisfied.  
//! I want to open the browser from Debian bash terminal with this simple syntax:  
//!
//! ```bash
//! www docs
//! www .
//! www rust-lang.org
//! ```
//!
//! I will make another alias:  
//!
//! ```bash
//! ln -sf "/usr/bin/wsl_open_browser" www
//! ```
//!
//! The command `ln -sf` is permanent and persistent. It makes a file that stays there forever.  
//!
// endregion: auto_md_to_doc_comments include README.md A //!

use unwrap::unwrap;

/// Inside WSL2 opens a html file in the browser that is in Win10  
/// The local file path is transformed between Linux and Win10 notation.  
/// If the argument is a directory then add index.html  
/// If the argument is . then use the current directory  
/// If there is no file, and the name contains something similar to an url, then open page on internet  
pub fn open_browser(arg_1: &str) {
    // region: Linux path
    // expand the relative path to absolute Linux path
    // canonicalize guarantee that the path exists
    // if the path does not exist it is probably an url
    let path = std::fs::canonicalize(arg_1);
    match path {
        Ok(path) => open_browser_from_path(path.as_path()),
        Err(_err) => new_process_for_browser(arg_1),
    }
}

/// open browser from absolute Linux path
fn open_browser_from_path(path: &std::path::Path) {
    let path = if path.is_file() {
        unwrap!(path.to_str()).to_string()
    } else {
        format!("{}/index.html", unwrap!(path.to_str()))
    };
    println!("path: {}", &path);
    let mut arg = String::new();
    if path.starts_with("/mnt/c/") {
        // Linux: /mnt/c/Users/Luciano/Downloads\index.html
        // Win10: c:\Users\Luciano\Downloads\index.html
        arg = format!(r#"file:///c:/{}"#, path.trim_start_matches("/mnt/c/"));
    } else if path.starts_with("/mnt/d/") {
        // Linux: /mnt/d/Users/Luciano/Downloads\index.html
        // Win10: d:\Users\Luciano\Downloads\index.html
        arg = format!(r#"file:///d:/{}"#, path.trim_start_matches("/mnt/d/"));
    } else if path.starts_with("/") {
        // Linux: /home/luciano/index.html
        // Win10: \\wsl$\Debian\home\luciano\index.html
        arg = format!(r#"file://///wsl$/Debian{}"#, path.replace(r#"\"#, "/"));
    }
    println!("uri: {}", &arg);
    new_process_for_browser(&arg);
}

/// open browser in new child process
fn new_process_for_browser(arg: &str) {
    let child = unwrap!(std::process::Command::new("/usr/bin/browser_in_win")
        .arg(arg)
        // ignore stderr
        .stderr(std::process::Stdio::null())
        .spawn());
    std::mem::forget(child);
}