<commit_before>//! Edit a `DataBase`.

use database::{write_database, DataBase};
use error::Result;
use ui::utils;
use ui::utils::{CommandList, CommandParser};

use std::error::Error;

#[derive(Clone, Copy, Debug)]
/// Editing commands.
enum Command {
    AddResidue,
    RemoveResidue,
    AddSubstrate,
    RemoveSubstrate,
    WriteToDisk,
    SetLocation,
    ShowDatabase,
    QuitAndSave,
    QuitWithoutSaving,
}

/// The main user menu.
pub fn user_menu(database: &mut DataBase) -> Result<&'static str> {
    let command_list: CommandList<Command> = vec![
        ("ra", Command::AddResidue, "Add a residue definition"),
        ("rr", Command::RemoveResidue, "Remove a residue definition"),
        ("sa", Command::AddSubstrate, "Add a substrate definition"),
        ("sr", Command::RemoveSubstrate, "Remove a substrate definition"),
        ("w", Command::WriteToDisk, "Write database to disk"),
        ("c", Command::SetLocation, "Change output location of database"),
        ("l", Command::ShowDatabase, "List database content"),
        ("f", Command::QuitAndSave, "Finish editing database"),
        ("a", Command::QuitWithoutSaving, "Abort editing and discard changes"),
    ];
    let commands = CommandParser::from_list(command_list);

    let path_backup = database.path.clone();
    let residues_backup = database.residue_defs.clone();
    let substrates_backup = database.substrate_defs.clone();

    println!("Editing the current database.\n");
    database.describe();
    println!("");

    loop {
        commands.print_menu();
        let input = utils::get_input_string("Selection")?;

        if let Some((cmd, tail)) = commands.get_selection_and_tail(&input) {
            match cmd {
                Command::AddResidue => {
                    match define_residue::user_menu() {
                        Ok(residue) => {
                            println!("Added residue '{}' to database.", residue.code);
                            database.residue_defs.push(residue);
                        },
                        Err(err) => println!("Could not create residue: {}", err.description()),
                    }
                },
                Command::RemoveResidue => {
                    match utils::remove_item(&mut database.residue_defs, &tail) {
                        Ok(i) => println!("Removed residue with index {} from database.", i),
                        Err(err) => println!("Could not remove residue: {}", err.description()),
                    }
                },
                Command::AddSubstrate => {
                    match define_substrate::user_menu(&database.residue_defs) {
                        Ok(substrate) => {
                            println!("Added substrate definition '{}' to database.",
                                     substrate.name);
                            database.substrate_defs.push(substrate);
                        },
                        Err(err) => println!("Could not create substrate: {}", err.description()),
                    }
                },
                Command::RemoveSubstrate => {
                    match utils::remove_item(&mut database.substrate_defs, &tail) {
                        Ok(i) => println!("Removed substrate with index {} from database.", i),
                        Err(err) => println!("Could not remove substrate: {}", err.description()),
                    }
                },
                Command::WriteToDisk => {
                    match write_database(&database) {
                        Ok(_) => println!("Wrote database to '{}'.",
                                          database.path.as_ref().unwrap().to_str().unwrap()),
                        Err(err) => println!("Could not write database: {}", err.description()),
                    }
                },
                Command::SetLocation => {
                    match database.set_path(&tail) {
                        Ok(_) => println!("Database path set to '{}'.",
                                          database.get_path_pretty()),
                        Err(err) => println!("Could not change database path: {}",
                                             err.description()),
                    }
                },
                Command::ShowDatabase => {
                    println!("");
                    database.describe();
                },
                Command::QuitAndSave => {
                    return Ok("Finished editing database.");
                },
                Command::QuitWithoutSaving => {
                    database.path = path_backup;
                    database.residue_defs = residues_backup;
                    database.substrate_defs = substrates_backup;

                    return Ok("Discarding changes to database.");
                },
            }
        } else {
            println!("Not a valid selection.");
        }

        println!("");
    }
}

mod define_residue {
    //! Define a new `ResidueBase`.
<commit_msg>Fix double-quote enclosing when printing database path after setting<commit_after>//! Edit a `DataBase`.

use database::{write_database, DataBase};
use error::Result;
use ui::utils;
use ui::utils::{CommandList, CommandParser};

use std::error::Error;

#[derive(Clone, Copy, Debug)]
/// Editing commands.
enum Command {
    AddResidue,
    RemoveResidue,
    AddSubstrate,
    RemoveSubstrate,
    WriteToDisk,
    SetLocation,
    ShowDatabase,
    QuitAndSave,
    QuitWithoutSaving,
}

/// The main user menu.
pub fn user_menu(database: &mut DataBase) -> Result<&'static str> {
    let command_list: CommandList<Command> = vec![
        ("ra", Command::AddResidue, "Add a residue definition"),
        ("rr", Command::RemoveResidue, "Remove a residue definition"),
        ("sa", Command::AddSubstrate, "Add a substrate definition"),
        ("sr", Command::RemoveSubstrate, "Remove a substrate definition"),
        ("w", Command::WriteToDisk, "Write database to disk"),
        ("c", Command::SetLocation, "Change output location of database"),
        ("l", Command::ShowDatabase, "List database content"),
        ("f", Command::QuitAndSave, "Finish editing database"),
        ("a", Command::QuitWithoutSaving, "Abort editing and discard changes"),
    ];
    let commands = CommandParser::from_list(command_list);

    let path_backup = database.path.clone();
    let residues_backup = database.residue_defs.clone();
    let substrates_backup = database.substrate_defs.clone();

    println!("Editing the current database.\n");
    database.describe();
    println!("");

    loop {
        commands.print_menu();
        let input = utils::get_input_string("Selection")?;

        if let Some((cmd, tail)) = commands.get_selection_and_tail(&input) {
            match cmd {
                Command::AddResidue => {
                    match define_residue::user_menu() {
                        Ok(residue) => {
                            println!("Added residue '{}' to database.", residue.code);
                            database.residue_defs.push(residue);
                        },
                        Err(err) => println!("Could not create residue: {}", err.description()),
                    }
                },
                Command::RemoveResidue => {
                    match utils::remove_item(&mut database.residue_defs, &tail) {
                        Ok(i) => println!("Removed residue with index {} from database.", i),
                        Err(err) => println!("Could not remove residue: {}", err.description()),
                    }
                },
                Command::AddSubstrate => {
                    match define_substrate::user_menu(&database.residue_defs) {
                        Ok(substrate) => {
                            println!("Added substrate definition '{}' to database.",
                                     substrate.name);
                            database.substrate_defs.push(substrate);
                        },
                        Err(err) => println!("Could not create substrate: {}", err.description()),
                    }
                },
                Command::RemoveSubstrate => {
                    match utils::remove_item(&mut database.substrate_defs, &tail) {
                        Ok(i) => println!("Removed substrate with index {} from database.", i),
                        Err(err) => println!("Could not remove substrate: {}", err.description()),
                    }
                },
                Command::WriteToDisk => {
                    match write_database(&database) {
                        Ok(_) => println!("Wrote database to '{}'.",
                                          database.path.as_ref().unwrap().to_str().unwrap()),
                        Err(err) => println!("Could not write database: {}", err.description()),
                    }
                },
                Command::SetLocation => {
                    match database.set_path(&tail) {
                        Ok(_) => println!("Database path set to {}.",
                                          database.get_path_pretty()),
                        Err(err) => println!("Could not change database path: {}",
                                             err.description()),
                    }
                },
                Command::ShowDatabase => {
                    println!("");
                    database.describe();
                },
                Command::QuitAndSave => {
                    return Ok("Finished editing database.");
                },
                Command::QuitWithoutSaving => {
                    database.path = path_backup;
                    database.residue_defs = residues_backup;
                    database.substrate_defs = substrates_backup;

                    return Ok("Discarding changes to database.");
                },
            }
        } else {
            println!("Not a valid selection.");
        }

        println!("");
    }
}

mod define_residue {
    //! Define a new `ResidueBase`.

{'fraction_non_alphanumeric': 0.12657349588660918, 'fraction_numerical': 0.0, 'mean_word_length': 1.576608784473953, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3922003', 'n_tokens_mistral': 2536, 'n_tokens_neox': 2405, 'n_words': 536}