Initial support for picking browsers

This only considers the first element of the browser definition, so
Flatpak apps are not supported yet

e.g. `/usr/bin/firefox URL` works, but

`flatpak run org.gnome.Epiphany URL` does not work yet.
4 files changed, 89 insertions(+), 32 deletions(-)

M Cargo.lock
M Cargo.toml
M choosier.toml
M src/main.rs
M Cargo.lock +47 -0
@@ 5,16 5,57 @@ name = "choosier"
 version = "0.1.0"
 dependencies = [
  "serde",
+ "serde_derive",
  "toml",
 ]
 
 [[package]]
+name = "proc-macro2"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
 name = "serde"
 version = "1.0.111"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d"
 
 [[package]]
+name = "serde_derive"
+version = "1.0.111"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb37da98a55b1d08529362d9cbb863be17556873df2585904ab9d2bc951291d0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
 name = "toml"
 version = "0.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"

          
@@ 22,3 63,9 @@ checksum = "ffc92d160b1eef40665be3a05630
 dependencies = [
  "serde",
 ]
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"

          
M Cargo.toml +2 -1
@@ 10,5 10,6 @@ repository = "https://hg.sr.ht/~michel-s
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-serde = "1.0.111"
+serde = "1.0"
+serde_derive = "1.0"
 toml = "0.5.6"

          
M choosier.toml +8 -4
@@ 1,4 1,8 @@ 
-default = "/usr/bin/firefox"
-overrides = [
-  [["netflix.com"], "/usr/bin/google-chrome"],
-]
+default = "firefox"
+
+[browsers]
+chrome = ["/usr/bin/google-chrome"]
+firefox = ["/usr/bin/firefox"]
+
+[overrides]
+chrome = ["netflix.com"]

          
M src/main.rs +32 -27
@@ 2,50 2,57 @@ 
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 
-extern crate serde;
+#[macro_use]
+extern crate serde_derive;
+extern crate toml;
 
+// use serde::de::Deserialize;
 use std::collections::HashMap;
 use std::io;
 
-// #[derive(Deserialize)]
+#[derive(Deserialize, Debug)]
 struct Config {
     default: String,
+    browsers: HashMap<String, Vec<String>>,
     overrides: HashMap<String, Vec<String>>,
 }
 
-fn parse(config_res: io::Result<String>) -> io::Result<Config> {
-    match config_res {
-        Ok(_config_str) => {
-            let m: HashMap<String, Vec<String>> = vec![(
-                "/usr/bin/google-chrome".to_string(),
-                vec!["netflix.com".to_string()],
-            )]
-            .into_iter()
-            .collect();
-            Ok(Config {
-                default: "/usr/bin/firefox".to_string(),
-                overrides: m,
-            })
-        }
-        Err(e) => Err(e),
-    }
+fn parse(config_str: &str) -> Result<Config, io::Error> {
+    let config: Config = toml::from_str(&config_str)?;
+    Ok(config)
 }
 
-fn read_config() -> io::Result<String> {
+fn read_config() -> Result<String, io::Error> {
     use std::fs::File;
     use std::io::prelude::*;
 
     let mut file = File::open("choosier.toml")?;
     let mut contents = String::new();
     file.read_to_string(&mut contents)?;
-    println!("{}", contents);
+    // println!("{}", contents);
     Ok(contents)
 }
 
+
 fn open_url(url: &str, config: Config) {
     use std::process::Command;
 
-    match Command::new(config.default).arg(url).spawn() {
+    let mut pick = config.default;
+
+    for (browser, urls) in config.overrides {
+        println!("{} = {:?}", browser, urls);
+        for u in urls {
+            match url.find(&u) {
+                Some(_) => {
+                    pick = browser.to_string();
+                }
+                None => ()
+            }
+        }
+    }
+
+    let cmd = &config.browsers[&pick][0];
+    match Command::new(cmd).arg(url).spawn() {
         Ok(_) => (),
         Err(e) => {
             println!("Failed to launch browser: {}", e);

          
@@ 62,10 69,8 @@ fn main() {
         return;
     }
     let url = &args[1];
-    match parse(read_config()) {
-        Ok(config) => open_url(url, config),
-        Err(_) => {
-            println!("Invalid configuration");
-        }
-    }
+
+    let config_str = read_config().unwrap();
+    let config = parse(&config_str).unwrap();
+    open_url(url, config);
 }