Repository: sharkdp/bat
File: src/bin/bat/config.rs (Rust)

Code before:
        .map(PathBuf::from)
        .filter(|config_path| config_path.is_file())
        .unwrap_or_else(|| PROJECT_DIRS.config_dir().join("config"))
}

pub fn generate_config_file() {
    let config_file = config_file();
    if config_file.exists() {
        println!("A config file already exists at: {}", config_file.to_string_lossy());

        print!("Overwrite? (y/n): ");
        let _ = io::stdout().flush();
        let mut decision = String::new();
        io::stdin().read_line(&mut decision).expect("Failed to read input");

        if !decision.trim().eq_ignore_ascii_case("Y") {
            return;
        }
    } else {
        let config_dir = config_file.parent().unwrap();
        if !config_dir.exists() {
            fs::create_dir(config_dir).expect("Unable to create config directory");
        }
    }

    let default_config = "# Specify desired theme (e.g. \"TwoDark\")
#--theme=\"TwoDark\"

# Enable this to use italic text on the terminal (not supported on all terminals):
#--italic-text=always

# Uncomment the following line to disable automatic paging:
#--paging=never

# Use C++ syntax for .ino files
#--map-syntax \"*.ino:C++\"

# Use \".gitignore\"-style highlighting for \".ignore\" files
#--map-syntax \".ignore:Git Ignore\"
";

    fs::write(&config_file, default_config).expect("Error writing config file!");
    println!("Success! Config file written to {}", config_file.to_string_lossy());
}

pub fn get_args_from_config_file() -> Result<Vec<OsString>, shell_words::ParseError> {
    Ok(fs::read_to_string(config_file())
        .ok()
        .map(|content| get_args_from_str(&content))
        .transpose()?
        .unwrap_or_else(|| vec![]))

Review comment (security):
To prevent having to escape all quotes in this default config, you can use a raw string:
``` rust
let default_config = r#"…
…"#;
```

Code after:
        .map(PathBuf::from)
        .filter(|config_path| config_path.is_file())
        .unwrap_or_else(|| PROJECT_DIRS.config_dir().join("config"))
}

pub fn generate_config_file() -> bat::errors::Result<()> {
    let config_file = config_file();
    if config_file.exists() {
        println!("A config file already exists at: {}", config_file.to_string_lossy());

        print!("Overwrite? (y/N): ");
        io::stdout().flush()?;
        let mut decision = String::new();
        io::stdin().read_line(&mut decision)?;

        if !decision.trim().eq_ignore_ascii_case("Y") {
            return Ok(());
        }
    } else {
        let config_dir = config_file.parent();
        match config_dir {
            Some(path) => fs::create_dir_all(path)?,
            None => return Ok(Err(format!("Unable to write config file to: {}", config_file.to_string_lossy()))?),
        }
    }

    let default_config = r#"# bat config

# Specify desired theme (e.g. "TwoDark").  Issue `bat --list-themes` for a list of all available themes
#--theme="TwoDark"

# Enable this to use italic text on the terminal (not supported on all terminals):
#--italic-text=always

# Uncomment the following line to disable automatic paging:
#--paging=never

# Use C++ syntax for .ino files
#--map-syntax "*.ino:C++"

# Use ".gitignore"-style highlighting for ".ignore" files
#--map-syntax ".ignore:Git Ignore"
"#;

    fs::write(&config_file, default_config)?;
    println!("Success! Config file written to {}", config_file.to_string_lossy());

    return Ok(());
}

pub fn get_args_from_config_file() -> Result<Vec<OsString>, shell_words::ParseError> {