Простой пользовательский интерфейс команды для условной логики


Это интерфейс командной строки обертывание для любых приложений, связанных условную логику. Я разместил источник здесь на Bitbucket.

Использование:

  1. Себя, используя в качестве отправной точки для серии Время обработки приложение для метеорологических данных. Параметры командной строки позволяют прыгать между несколькими не связанными с ними функциями, а также для заполнения объекты входы вручную. Я могу загрузить данные в приложение памяти через несколько методов, в Excel, CSV или заполнить вручную, а затем выбрать, какой тест запустить, т. е. раз в Погода раз серия загрузилась, я могу выбрать с помощью командной строки ли, чтобы вычислить стандартное отклонение, значит. В код я сохранил все механизмы / классы для этого.
  2. Я думаю, это будет полезно для людей, изучающих программирование в школе проекты - это отнимает много работы, когда обычно начинается с пустой файл и добавить часто используемые функции и интерфейс
    для вызова различных функций

Любая обратная связь на макете код будет оценен по достоинству, а в частности:

  1. Как файлы структурированы
  2. Структуру Settings Синглтон и CLI пространства имен, который содержит функции для обработки команды ввода от пользователя
  3. Отзывы о использовании DEFINES файл, как я сделал это хорошая практика
  4. Ли я заполнить привилегии-это хорошая практика
  5. Является ли это хорошая идея, чтобы использовать оболочку, как это, чтобы начать любой проект

Структура Файла:

  • 0_UTILITIES - некоторые базовые служебные функции, которые часто всплывают и они обычно представлены в интро к C++ книги
  • 1_COMMAND_LINE_INTERFACE - набор функций, который позволяет управлять интерфейсом
  • 2_ACTUAL_APP - фактическое приложение код, который вы хотите использовать здесь идет (некоторые фиктивные функции заполняется для иллюстрации того, как информацию, полученную от пользователей упакован в объекты и передавать приложения

Код товара 1 - заявление о настройки одноэлементных и связанные с ними функции:

struct command_info_container{
    void* container_1;
    void* container_2;
}; // this is an object to pass information between commands user invokes. each next node always knows what to cast the void container to

class command;

class user{
public:
    user(){}
    user(std::string pw):password(pw){}
    user(std::string pw,std::map<std::string,int> cp):password(pw),command_permissions(cp){}
    std::string password;
    std::map<std::string,int> command_permissions;
}; // allows for different user with customized command_permissions objects. The command_permissions matches the text command invoke and allows to remove user's access to certain commands



namespace cli{ /// cli - command line interface. Certain functions which could also be in Settings singleton are implemented here. Not sure if this is the right design practice

void run_authorisation(command_info_container*); /// every function which is potentially packageable into a vector of functions takes the same shape, with an input of command_info_container pointer
void display_welcome_message(command_info_container*);
void display_completion_message(command_info_container*);

void run_command_junction(COMMAND_JUNCTION_KEY key,command_info_container* user_data); /// this pulls out the vector of commands packaged to a particular key. Commands are stored in Singleton Settings
void display_available_commands(COMMAND_JUNCTION_KEY key); /// at each stage, user is presented with a printout of available commands
std::string prompt_for_command(std::string message_to_user_if_different_from_default);
command match_input_text_to_a_command(std::string cmd,COMMAND_JUNCTION_KEY key);

void exit_program(command_info_container* info_to_pass);

void run_command_junction_C_MAIN(command_info_container* info_to_pass);
void run_command_junction_C_QUIT(command_info_container* info_to_pass);
void run_command_junction_C_GO_BACK(command_info_container* info_to_pass);
void run_command_junction_C_TEST(command_info_container* info_to_pass);
void run_command_junction_C_CHANGE_USER(command_info_container* info_to_pass); /// these functions are wrappers around run_command_junction, invoking a particular key - i.e. run_command_junction_C_MAIN invokes the C_MAIN command junction

void test_code_snippet(command_info_container* info_to_pass); /// this is for testing a snippet, for debugging purposes

}



struct command{ /// commands are contained in this class, main contents being pointer to immediate function to execute, and pointer to the function to execute after first function finishes running
    command(){}
    command(std::vector<std::string> inv, std::string desc,ptr_to_command_func p,ptr_to_command_func pn = &cli::run_command_junction_C_MAIN,std::string w = EMPTY_STRING,std::string cm = EMPTY_STRING):
        text_of_command(inv),description_of_command(desc),func_to_execute(p),next_func_to_execute(pn){}
    command(std::string inv, std::string desc,ptr_to_command_func p,ptr_to_command_func pn = &cli::run_command_junction_C_MAIN,std::string w = EMPTY_STRING,std::string cm = EMPTY_STRING):
        description_of_command(desc),func_to_execute(p),next_func_to_execute(pn){text_of_command.push_back(inv);}

std::vector<std::string> text_of_command;
std::string description_of_command;

ptr_to_command_func func_to_execute = nullptr;
ptr_to_command_func next_func_to_execute = nullptr;

};

class settings{
settings();
    map_of_command_junctions command_storage;
    std::map<std::string,user> usernames_passwords_privileges;

public:
    static settings& get(){static settings S; return S;}

    bool perform_authorisation(std::string username,std::string password);
    void set_active_user(std::string username);

    void populate_available_usernames_and_passwords();
    void initialise_command_tree();
    void apply_permissions_to_command_availability();
    void add_auto_commands_to_junction(COMMAND_JUNCTION_KEY key);
    void add_numerical_command_invokes(COMMAND_JUNCTION_KEY key);
    command match_input_text_to_a_command(std::string cmd,COMMAND_JUNCTION_KEY key);


    bool quit_flag;
    bool require_password_on_startup;
    bool use_admin_permissions_by_default;

    map_of_command_junctions permissioned_command_tree;

    std::string active_user;

    COMMAND_JUNCTION_KEY previous_junction;
    COMMAND_JUNCTION_KEY current_junction;

    command cmd_J1_quit_confirmation;
    command cmd_J0_main_menu;
    command cmd_J1_go_back;
    command cmd_login;
};

Код товара 2 - осуществление настройки синглтон:

#include "0_UTILITIES/Includes.h"
#include COMMAND_LINE_INTERFACE

settings::settings(){

quit_flag = false;
require_password_on_startup = true;
use_admin_permissions_by_default = true;

populate_available_usernames_and_passwords();
initialise_command_tree();

} 

void settings::populate_available_usernames_and_passwords(){

usernames_passwords_privileges["admin"] = user("adminpassword");



std::map<std::string,int> normaluser_permissions;
normaluser_permissions["LOGIN"] = 0; 

usernames_passwords_privileges["normaluser"] = user("normalpassword",normaluser_permissions);

if (use_admin_permissions_by_default) {active_user = "admin";} else {active_user = "normaluser";}
}

Код товара 3 - заполнение команд пользователь может использовать в настройках синглтон:

void settings::initialise_command_tree(){

command_storage.clear();
command cmd_continue_with_default_user("CONTD","Continue with default user",&cli::run_command_junction_C_MAIN);
cmd_login = command("LOGIN","Change user",&cli::run_authorisation);

command cmd_F_exit_program("FINALQUIT","Exit for good",&cli::exit_program);
cmd_J0_main_menu = command ("MAIN","Revert to main menu",&cli::run_command_junction_C_MAIN);
command cmd_J1_test_snippet("SNPT","Test a code snippet",&cli::test_code_snippet);
cmd_J1_go_back = command("GOBACK","Go back",&cli::run_command_junction_C_GO_BACK);

command cmd_J1_prompt_for_test_inputs("RTST","Input data to run Test",&cli::run_command_junction_C_TEST);

cmd_J1_quit_confirmation = command("EXIT","Confirm exiting program",&cli::run_command_junction_C_QUIT);

command cmd_F0_J1_test_manual_input("TSTM","Test - input via console",&cli::prompt_for_single_test_inputs,&cli::run_test);
command cmd_F1_J1_test_from_xls("TXLS","Test - input via xls",&cli::load_test_input_xls,&cli::run_test);
command cmd_F2_J1_test_from_csv("TCSV","Test - input via csv",&cli::load_test_input_csv,&cli::run_test);

command_storage[COMMAND_JUNCTION_KEY::C_MAIN].push_back(cmd_J1_quit_confirmation);
command_storage[COMMAND_JUNCTION_KEY::C_MAIN].push_back(cmd_J1_test_snippet);
command_storage[COMMAND_JUNCTION_KEY::C_MAIN].push_back(cmd_J1_prompt_for_test_inputs);
command_storage[COMMAND_JUNCTION_KEY::C_MAIN].push_back(cmd_login);

command_storage[COMMAND_JUNCTION_KEY::C_QUIT].push_back(cmd_F_exit_program);

command_storage[COMMAND_JUNCTION_KEY::C_TEST].push_back(cmd_F0_J1_test_manual_input);
command_storage[COMMAND_JUNCTION_KEY::C_TEST].push_back(cmd_F1_J1_test_from_xls);
command_storage[COMMAND_JUNCTION_KEY::C_TEST].push_back(cmd_F2_J1_test_from_csv);

command_storage[COMMAND_JUNCTION_KEY::C_CHANGE_USER].push_back(cmd_continue_with_default_user);
command_storage[COMMAND_JUNCTION_KEY::C_CHANGE_USER].push_back(cmd_login);

apply_permissions_to_command_availability();

for (auto& command_keys: permissioned_command_tree) { 
    add_auto_commands_to_junction(command_keys.first);
    add_numerical_command_invokes(command_keys.first);
}

}


Комментарии