use std::ffi::{OsStr, OsString};

fn exec_runner<S: AsRef<OsStr>>(args: &[S]) {
    use std::os::unix::process::CommandExt;
    let err = std::process::Command::new(&args[0]).args(&args[1..]).exec();
    println!("error: {}", err);
    if let Some(err) = err.raw_os_error() {
        std::process::exit(err);
    }
    std::process::exit(-1)
}

fn main() {
    let home = std::env::home_dir().unwrap();

    let mut sbt_jar = std::path::PathBuf::from(home);
    sbt_jar.push(".sbt/launchers/0.13.13/sbt-launch.jar");
    let sbt_jar = sbt_jar;

    let extra_jvm_opts = [OsStr::new("-Xms512m").to_os_string(),
                          OsStr::new("-Xmx1536m").to_os_string(),
                          OsStr::new("-Xss2m").to_os_string()];
    let java_args: [OsString; 0] = [];
    let sbt_commands: [OsString; 0] = [];
    let residual_args: [OsString; 0] = [];

    let mut exec_args: Vec<OsString> = Vec::new();
    exec_args.push(OsStr::new("java").to_os_string());
    exec_args.extend_from_slice(&extra_jvm_opts);
    exec_args.extend_from_slice(&java_args);
    exec_args.extend_from_slice(&[OsStr::new("-jar").to_os_string(), sbt_jar.into_os_string()]);
    exec_args.push(OsStr::new("shell").to_os_string());
    exec_args.extend_from_slice(&sbt_commands);
    exec_args.extend_from_slice(&residual_args);
    let exec_args = exec_args;

    exec_runner(&exec_args)
}

fn main() {
    let home = std::env::home_dir().unwrap();
    let mut sbt_jar = std::path::PathBuf::from(home);
    sbt_jar.push(".sbt/launchers/0.13.13/sbt-launch.jar");
    let sbt_jar = sbt_jar;
    use std::os::unix::process::CommandExt;
    let err = std::process::Command::new("java")
        .args(&["-Xms512m", "-Xmx1536m", "-Xss2m"])
        .args(&[&"-jar".as_ref(), &sbt_jar.as_os_str()])
        .arg("shell")
        .exec();
    println!("error: {}", err);
    if let Some(err) = err.raw_os_error() {
        std::process::exit(err);
    }
    std::process::exit(-1)
}

--- 
+++ 
@@ -1,17 +1,38 @@
-fn main() {
-    let home = std::env::home_dir().unwrap();
-    let mut sbt_jar = std::path::PathBuf::from(home);
-    sbt_jar.push(".sbt/launchers/0.13.13/sbt-launch.jar");
-    let sbt_jar = sbt_jar;
+use std::ffi::{OsStr, OsString};
+
+fn exec_runner<S: AsRef<OsStr>>(args: &[S]) {
     use std::os::unix::process::CommandExt;
-    let err = std::process::Command::new("java")
-        .args(&["-Xms512m", "-Xmx1536m", "-Xss2m"])
-        .args(&[&"-jar".as_ref(), &sbt_jar.as_os_str()])
-        .arg("shell")
-        .exec();
+    let err = std::process::Command::new(&args[0]).args(&args[1..]).exec();
     println!("error: {}", err);
     if let Some(err) = err.raw_os_error() {
         std::process::exit(err);
     }
     std::process::exit(-1)
 }
+
+fn main() {
+    let home = std::env::home_dir().unwrap();
+
+    let mut sbt_jar = std::path::PathBuf::from(home);
+    sbt_jar.push(".sbt/launchers/0.13.13/sbt-launch.jar");
+    let sbt_jar = sbt_jar;
+
+    let extra_jvm_opts = [OsStr::new("-Xms512m").to_os_string(),
+                          OsStr::new("-Xmx1536m").to_os_string(),
+                          OsStr::new("-Xss2m").to_os_string()];
+    let java_args: [OsString; 0] = [];
+    let sbt_commands: [OsString; 0] = [];
+    let residual_args: [OsString; 0] = [];
+
+    let mut exec_args: Vec<OsString> = Vec::new();
+    exec_args.push(OsStr::new("java").to_os_string());
+    exec_args.extend_from_slice(&extra_jvm_opts);
+    exec_args.extend_from_slice(&java_args);
+    exec_args.extend_from_slice(&[OsStr::new("-jar").to_os_string(), sbt_jar.into_os_string()]);
+    exec_args.push(OsStr::new("shell").to_os_string());
+    exec_args.extend_from_slice(&sbt_commands);
+    exec_args.extend_from_slice(&residual_args);
+    let exec_args = exec_args;
+
+    exec_runner(&exec_args)
+}
Define arg groups & extract exec_runner
