Add --min option to specify a minimum version

This is handy in scripts or keybindings.
3 files changed, 72 insertions(+), 22 deletions(-)

M Cargo.toml
M src/bin/brightctl.rs
M src/cli.rs
M Cargo.toml +1 -1
@@ 1,6 1,6 @@ 
 [package]
 name = "bright"
-version = "1.0.0"
+version = "1.1.0"
 description = "Screen backlight control"
 homepage = "https://bitbucket.org/flub/bright"
 authors = ["Floris Bruynooghe <flub@devork.be>"]

          
M src/bin/brightctl.rs +51 -21
@@ 21,6 21,9 @@ struct AppConfig {
 
     // D-Bus mode
     dbus: DBusMode,
+
+    // Minimum brightness value
+    minimum: Option<u32>,
 }
 
 

          
@@ 50,7 53,8 @@ impl AppConfig {
             ("get", _) => Action::Get,
             ("watch", _) => Action::Watch,
             (action, Some(sub_matches)) => {
-                let num = value_t_or_exit!(sub_matches.value_of("NUM"), u32);
+                let num = value_t!(sub_matches.value_of("NUM"), u32)
+                    .unwrap_or_else(|e| e.exit());
                 match action {
                     "set" => Action::Set(num),
                     "increment" => Action::Incr(num),

          
@@ 76,10 80,16 @@ impl AppConfig {
             Some(_) => DBusMode::Auto,
             None => DBusMode::Auto
         };
+        let min = match matches.value_of("min") {
+            // Already validated in clap, so .unwrap() should be safe.
+            Some(s) => Some(s.trim().parse::<u32>().unwrap()),
+            None => None
+        };
         Ok(AppConfig{
             action: action,
             devices: devices,
             dbus: dbus,
+            minimum: min,
         })
     }
 }

          
@@ 209,17 219,29 @@ fn set_brightness_dbus(cfg: &AppConfig) 
         }
         match cfg.action {
             Action::Set(n) => {
-                obj.set(bright::dbus::DEVICE_IFACE, "Brightness", n)?;
+                let val = match cfg.minimum {
+                    Some(min) => std::cmp::max(n, min),
+                    None => n
+                };
+                obj.set(bright::dbus::DEVICE_IFACE, "Brightness", val)?;
             },
             Action::Incr(n) => {
                 let cur: u32 = obj.get(bright::dbus::DEVICE_IFACE,
                                        "Brightness")?;
-                obj.set(bright::dbus::DEVICE_IFACE, "Brightness", cur + n)?;
+                let val = match cfg.minimum {
+                    Some(min) => std::cmp::max(cur + n, min),
+                    None => cur + n
+                };
+                obj.set(bright::dbus::DEVICE_IFACE, "Brightness", val)?;
             },
             Action::Decr(n) => {
                 let cur: u32 = obj.get(bright::dbus::DEVICE_IFACE,
                                        "Brightness")?;
-                obj.set(bright::dbus::DEVICE_IFACE, "Brightness", cur - n)?;
+                let val = match cfg.minimum {
+                    Some(min) => std::cmp::max(cur - n, min),
+                    None => cur - n
+                };
+                obj.set(bright::dbus::DEVICE_IFACE, "Brightness", val)?;
             },
             _ => panic!("Action other then set/incr/decr")
         }

          
@@ 229,28 251,36 @@ fn set_brightness_dbus(cfg: &AppConfig) 
 
 
 fn set_brightness_direct(cfg: &AppConfig) -> Result<(), failure::Error> {
-    let mut success = true;
     let devices = create_devices(cfg.devices.clone())?;
     for dev in devices.iter() {
-        let ret = match cfg.action {
-            Action::Set(n)  => dev.set(n),
-            Action::Incr(n) => dev.incr(n),
-            Action::Decr(n) => dev.decr(n),
+        match cfg.action {
+            Action::Set(n)  => {
+                let val = match cfg.minimum {
+                    Some(min) => std::cmp::max(n, min),
+                    None => n
+                };
+                dev.set(val)?;
+            },
+            Action::Incr(n) => {
+                let cur = dev.get()?;
+                let val = match cfg.minimum {
+                    Some(min) => std::cmp::max(cur + n, min),
+                    None => cur + n
+                };
+                dev.incr(val)?;
+            },
+            Action::Decr(n) => {
+                let cur = dev.get()?;
+                let val = match cfg.minimum {
+                    Some(min) => std::cmp::max(cur - n, min),
+                    None => cur - n
+                };
+                dev.decr(val)?;
+            },
             _ => panic!("Action other then set/incr/decr")
         };
-        match ret {
-            Ok(_) => (),
-            Err(e) => {
-                eprintln!("Failed to set {}", dev);
-                print_error(e);
-                success = false;
-            },
-        }
     }
-    match success {
-        true => Ok(()),
-        false => Err(failure::err_msg("Some devices failed")),
-    }
+    Ok(())
 }
 
 

          
M src/cli.rs +20 -0
@@ 14,21 14,31 @@ only modify one or more devices use the 
         .setting(AppSettings::ColoredHelp)
         .arg(Arg::with_name("devices")
              .long("devices")
+             .global(true)
              .takes_value(true)
              .value_name("NAMES")
              .use_delimiter(true)
              .help("Comma-separated device names to use"))
         .arg(Arg::with_name("dbus")
              .long("dbus")
+             .global(true)
              .possible_values(&["auto", "only", "no"])
              .default_value("auto")
              .help("Whether to use dbus"))
+        .arg(Arg::with_name("min")
+             .long("min")
+             .global(true)
+             .takes_value(true)
+             .validator(is_int)
+             .value_name("MIN")
+             .help("Do not set brightness lower then this"))
         .subcommand(SubCommand::with_name("get")
                     .about("Get the current brightness"))
         .subcommand(SubCommand::with_name("set")
                     .about("Set the brighness")
                     .arg(Arg::with_name("NUM")
                          .takes_value(true)
+                         .validator(is_int)
                          .required(true)
                          .index(1)
                          .help("Percentage to set brightness too")))

          
@@ 37,6 47,7 @@ only modify one or more devices use the 
                     .about("Increment the brightness")
                     .arg(Arg::with_name("NUM")
                          .takes_value(true)
+                         .validator(is_int)
                          .required(true)
                          .index(1)
                          .help("Percentage to increase brightness with")))

          
@@ 45,6 56,7 @@ only modify one or more devices use the 
                     .about("Decrement the brightness")
                     .arg(Arg::with_name("NUM")
                          .takes_value(true)
+                         .validator(is_int)
                          .required(true)
                          .index(1)
                          .help("Percentalge to decrease brightness with")))

          
@@ 53,6 65,14 @@ only modify one or more devices use the 
 }
 
 
+fn is_int(arg: String) -> Result<(), String> {
+    match arg.trim().parse::<u32>() {
+        Ok(_) => Ok(()),
+        Err(_) => Err(String::from(format!("Not an integer: {}", arg)))
+    }
+}
+
+
 pub fn brightd_app() -> App<'static, 'static> {
     App::new("brightd")
             .version(crate_version!())