├── .gitignore ├── .travis.yml ├── Ginseng.h ├── LICENSE.txt ├── Terminal.h ├── changelog.md ├── main.cpp ├── media ├── logo.png ├── logo.svg └── sshot.1.png ├── readme.md └── tests ├── CMakeLists.txt └── tests.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.out 2 | .clang-format 3 | .vscode 4 | main.cpp 5 | build -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | 2 | language: cpp 3 | sudo: required 4 | dist: trusty 5 | compiler: 6 | - gcc 7 | os: 8 | - linux 9 | 10 | before_install: 11 | - echo "BEFORE INSTALL START" 12 | - gem install bundler 13 | - echo "BEFORE INSTALL END" 14 | 15 | branches: 16 | only: 17 | - master 18 | 19 | install: 20 | - sudo apt-get install libboost-all-dev 21 | 22 | script: 23 | - cd ${TRAVIS_BUILD_DIR}/tests 24 | - cmake . 25 | - make && ./libtest -------------------------------------------------------------------------------- /Ginseng.h: -------------------------------------------------------------------------------- 1 | #ifndef __Ginseng_H 2 | #define __Ginseng_H 3 | 4 | #include "Terminal.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define COL_WIDTH 15 12 | 13 | using CmdCallback = std::function)>; 14 | 15 | enum Exit 16 | { 17 | SUCCESS = 0, 18 | INVALID_ARGUMENTS = 1, 19 | ERROR = 9 20 | }; 21 | 22 | /** 23 | * @struct Help 24 | * Struct intended to hold a command's help information 25 | **/ 26 | struct Help 27 | { 28 | std::string description; 29 | std::string arguments; 30 | 31 | Help() 32 | { 33 | } 34 | 35 | Help(std::string t_desc, std::string t_args) : description(t_desc), arguments(t_args) 36 | { 37 | } 38 | }; 39 | 40 | /** 41 | * @struct Command 42 | * Struct to hold all the information related with a command. 43 | */ 44 | struct Command 45 | { 46 | std::string name; 47 | CmdCallback cb; 48 | Help help; 49 | 50 | Command() 51 | { 52 | } 53 | 54 | Command(std::string t_name, CmdCallback t_cb, Help t_help) : name(t_name), cb(t_cb), help(t_help) 55 | { 56 | } 57 | }; 58 | 59 | /** 60 | * @class Ginseng 61 | * This class handles all command specifict functions 62 | * Intended to provide a simplified interface to buidl and mantain a REPL tool 63 | **/ 64 | class Ginseng 65 | { 66 | private: 67 | std::string delimiter; 68 | std::map commands; 69 | void clear_screen(); 70 | Command parse_command(std::string cmd_str); 71 | void print_help(); 72 | void print_delimiter(); 73 | void handle_error(int err); 74 | std::function greet_handler; 75 | std::function farewell_handler; 76 | std::string pad_left(const std::string &str, const size_t length, const char chr) const; 77 | std::string pad_right(const std::string &str, const size_t length, const char chr) const; 78 | std::vector parse(std::string str); 79 | Terminal term; 80 | 81 | public: 82 | void add_command(std::string name, CmdCallback cb, Help help); 83 | void start(); 84 | Ginseng(std::string delim, std::function greet, std::function farewell); 85 | 86 | template 87 | void printf(const std::string &msg, Args... args); 88 | void println(const std::string &msg); 89 | }; 90 | 91 | Ginseng::Ginseng(std::string delim, std::function greet, std::function farewell) 92 | : delimiter(delim), greet_handler(greet), farewell_handler(farewell) 93 | { 94 | } 95 | 96 | /** 97 | * Prints a formated message into current cursor position. 98 | * @param std::string text with format 99 | * @param multiple formatting arguments 100 | **/ 101 | template 102 | void Ginseng::printf(const std::string &msg, Args... args) 103 | { 104 | term.printf(msg, args...); 105 | } 106 | 107 | /** 108 | * Helper function to clear screen 109 | **/ 110 | void Ginseng::println(const std::string &msg) 111 | { 112 | term.println(msg); 113 | } 114 | 115 | /** 116 | * Helper function to clear screen 117 | * OS independent. 118 | **/ 119 | void Ginseng::clear_screen() 120 | { 121 | term.cls(); 122 | } 123 | 124 | /** 125 | * Helper function to pad string to the left 126 | * @param std::string string to be padded 127 | * @param size_t final lenght of the string 128 | * @param char char to pad with 129 | * @return std::string padded string. 130 | **/ 131 | std::string Ginseng::pad_left(const std::string &str, const size_t length, const char chr) const 132 | { 133 | std::string ret(str); 134 | ret.insert(ret.begin(), length - str.size(), chr); 135 | return ret; 136 | } 137 | 138 | /** 139 | * Helper function to pad string to the right 140 | * @param std::string string to be padded 141 | * @param size_t final lenght of the string 142 | * @param char char to pad with 143 | * @return std::string padded string. 144 | **/ 145 | std::string Ginseng::pad_right(const std::string &str, const size_t length, const char chr) const 146 | { 147 | std::string ret(str); 148 | ret.insert(ret.end(), length - str.size(), chr); 149 | return ret; 150 | } 151 | 152 | /** 153 | * Helper function to print help for both preshipped functions and user defined commands 154 | **/ 155 | void Ginseng::print_help() 156 | { 157 | term.println(""); 158 | term.printf("%s %s %s\n", pad_right("Commmand", COL_WIDTH, ' ').c_str(), pad_right("Args", COL_WIDTH, ' ').c_str(), "Description"); 159 | term.println(pad_right("", COL_WIDTH * 3, '-').c_str()); 160 | 161 | for (const auto &cmd : commands) 162 | { 163 | term.printf("%s %s %s\n", pad_right(cmd.second.name, COL_WIDTH, ' ').c_str(), pad_right(cmd.second.help.arguments, COL_WIDTH, ' ').c_str(), 164 | cmd.second.help.description.c_str()); 165 | } 166 | 167 | term.printf("%s %s %s\n", pad_right("exit", COL_WIDTH, ' ').c_str(), pad_right("", COL_WIDTH, ' ').c_str(), "Terminates the execution"); 168 | term.printf("%s %s %s\n", pad_right("cls", COL_WIDTH, ' ').c_str(), pad_right("", COL_WIDTH, ' ').c_str(), "Clears the screen"); 169 | term.println(pad_right("", COL_WIDTH * 3, '-').c_str()); 170 | } 171 | 172 | /** 173 | * Helper function to print the defined delimiter at current cursor position. 174 | */ 175 | void Ginseng::print_delimiter() 176 | { 177 | term.printf("%s ", delimiter.c_str()); 178 | } 179 | 180 | /** 181 | * Will split a string. Every token is considered to end at a " " (space). 182 | * @param std::string string to be tokenized 183 | * @return std::vector token array 184 | */ 185 | std::vector Ginseng::parse(std::string str) 186 | { 187 | std::vector tokens; 188 | std::istringstream src(str); 189 | std::string tok; 190 | 191 | while (std::getline(src, tok, ' ')) 192 | { 193 | tokens.push_back(tok); 194 | } 195 | 196 | return tokens; 197 | } 198 | 199 | /** 200 | * Handle execution ERROR 201 | * @param int Error code. See enum Exit. 202 | */ 203 | void Ginseng::handle_error(int err) 204 | { 205 | switch (err) 206 | { 207 | case Exit::INVALID_ARGUMENTS: 208 | term.println("Invalid Arguments, type \"help\" for details."); 209 | break; 210 | 211 | default: 212 | break; 213 | } 214 | } 215 | 216 | /** 217 | * Starts the execution of the REPL. 218 | * Thought to be called independently to allow configurations prior to launch 219 | */ 220 | void Ginseng::start() 221 | { 222 | greet_handler(); 223 | 224 | while (true) 225 | { 226 | 227 | std::string cmd_str = term.prompt(delimiter); 228 | term.println(""); 229 | std::vector args = parse(cmd_str); 230 | 231 | if (args[0] == std::string("exit") || args[0] == std::string("quit") || args[0] == std::string(":q")) 232 | break; 233 | 234 | if (args[0] == "help" || args[0] == "?" || args[0] == ":h") 235 | { 236 | print_help(); 237 | continue; 238 | } 239 | 240 | if (args[0] == "cls") 241 | { 242 | term.cls(); 243 | continue; 244 | } 245 | 246 | // If command is found insid the commands list. 247 | auto it = commands.find(args[0]); 248 | if (it != commands.end()) 249 | { 250 | Command cmd = it->second; 251 | int res = cmd.cb(args); 252 | if (res != Exit::SUCCESS) 253 | { 254 | handle_error(res); 255 | } 256 | } 257 | else 258 | { 259 | term.println("Command not found."); 260 | } 261 | } 262 | 263 | farewell_handler(); 264 | } 265 | 266 | /** 267 | * Adds a command to the command pool 268 | * @param std::string identifier to be used for invoking the command. 269 | * @param std::function)> handler to be called when the command is invoked 270 | * @param Help struct containing help for given command. 271 | **/ 272 | void Ginseng::add_command(std::string name, CmdCallback cb, Help help) 273 | { 274 | commands[name] = Command(name, cb, help); 275 | } 276 | 277 | #endif 278 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Othneil Drew 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Terminal.h: -------------------------------------------------------------------------------- 1 | #ifndef __Terminal_H 2 | #define __Terminal_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class Terminal 10 | { 11 | public: 12 | template 13 | void printf(const std::string &msg, Args... args); 14 | void println(const std::string &msg); 15 | void cls(); // clear screen; 16 | std::string prompt(const std::string delimiter); 17 | 18 | Terminal(); 19 | ~Terminal(); 20 | 21 | private: 22 | void init_screen(); 23 | void destroy_screen(); 24 | void refresh_line(const std::string &new_value, const std::string delimiter); 25 | void end_command(const std::string &command); 26 | void cr(); // carriage return; 27 | std::string delimiter = "> "; 28 | 29 | std::vector history; 30 | std::vector::iterator it; 31 | 32 | WINDOW *_window; 33 | }; 34 | 35 | Terminal::Terminal() 36 | { 37 | init_screen(); 38 | } 39 | 40 | Terminal::~Terminal() 41 | { 42 | destroy_screen(); 43 | } 44 | 45 | /** 46 | * OS safe screen clear 47 | **/ 48 | void Terminal::cls() 49 | { 50 | wmove(_window, 0, 0); 51 | wclrtobot(_window); 52 | } 53 | 54 | /** 55 | * Refreshes line with value and prepends delimiter 56 | * @param std::string new line value 57 | * @param std::string delimiter 58 | **/ 59 | void Terminal::refresh_line(const std::string &new_value, const std::string delimiter) 60 | { 61 | int x; 62 | int y; 63 | getyx(_window, y, x); 64 | wmove(_window, y, 0); 65 | wclrtoeol(_window); 66 | wprintw(_window, "%s %s", delimiter.c_str(), new_value.c_str()); 67 | wrefresh(_window); 68 | } 69 | 70 | /** 71 | * Adds carriage return to current line 72 | **/ 73 | void Terminal::cr() 74 | { 75 | wprintw(_window, "\n"); 76 | wrefresh(_window); 77 | } 78 | 79 | /** 80 | * Ends command prompt. 81 | * Adds command to history and resets iterator pointer. 82 | **/ 83 | void Terminal::end_command(const std::string &command) 84 | { 85 | if (command == "" || command == "...") 86 | return; 87 | history.push_back(command); 88 | it = history.end(); 89 | } 90 | 91 | /** 92 | * Prints a formated message into current cursor position. 93 | * @param std::string text with format 94 | * @param multiple formatting arguments 95 | **/ 96 | template 97 | void Terminal::printf(const std::string &msg, Args... args) 98 | { 99 | wprintw(_window, msg.c_str(), args...); 100 | wrefresh(_window); 101 | } 102 | 103 | /** 104 | * Prints a string to current cursor position. 105 | * Adds carriage return. 106 | **/ 107 | void Terminal::println(const std::string &msg) 108 | { 109 | wprintw(_window, msg.c_str()); 110 | cr(); 111 | } 112 | 113 | /** 114 | * Prompts for user input. 115 | * @param delimiter Delimiter to be used in prompt 116 | **/ 117 | std::string Terminal::prompt(const std::string delimiter = ">") 118 | { 119 | cr(); 120 | refresh_line("", delimiter); 121 | int c = wgetch(_window); 122 | std::string command; 123 | bool eoc = false; 124 | 125 | while (!eoc) //!= CR 126 | { 127 | switch (c) 128 | { 129 | 130 | case KEY_UP: 131 | // Handle key up press 132 | // Retrieves previous from history 133 | { 134 | if (it > history.begin()) 135 | it--; 136 | ; 137 | command = (*it); 138 | break; 139 | } 140 | 141 | case KEY_DOWN: 142 | // Handles key down press 143 | // Retrieves following command from history 144 | { 145 | if (it < history.end()) 146 | it++; 147 | if (it == history.end()) 148 | command = ""; 149 | else 150 | command = (*it); 151 | break; 152 | } 153 | 154 | case 127: 155 | // Handles backspace press 156 | // Removes last charater from buffered command 157 | { 158 | command.pop_back(); 159 | break; 160 | } 161 | 162 | case 10: 163 | // Return key 164 | { 165 | eoc = command.size() > 0; 166 | break; 167 | } 168 | 169 | default: 170 | // Handles non special characters 171 | // Appends character to buffered command 172 | { 173 | if (c != -1) 174 | command += c; // Input in current loop (-1 == ERR) 175 | break; 176 | } 177 | } 178 | refresh_line(command, delimiter); 179 | c = wgetch(_window); 180 | } 181 | 182 | end_command(command); 183 | 184 | if (command == "" || command == "...") 185 | return ""; 186 | return command; 187 | } 188 | 189 | /** 190 | * Initializes ncurses screen 191 | * Will only create one default screen to handle the whole terminal 192 | **/ 193 | void Terminal::init_screen() 194 | { 195 | // NCURSES init 196 | initscr(); 197 | cbreak(); // break with ctrl + c 198 | noecho(); // dont echo inputs 199 | 200 | int height, width, start_y, start_x; 201 | getmaxyx(stdscr, height, width); 202 | 203 | start_y = 0; 204 | start_x = 0; 205 | 206 | _window = newwin(height, width, start_y, start_x); 207 | 208 | keypad(_window, true); //Use keypad` 209 | nodelay(_window, true); 210 | scrollok(_window, TRUE); //Enable scroll 211 | 212 | history.push_back("..."); 213 | it = history.end(); 214 | 215 | wclrtobot(_window); 216 | } 217 | 218 | void Terminal::destroy_screen() 219 | { 220 | // deallocates memory and ends ncurses 221 | endwin(); 222 | } 223 | 224 | #endif -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [1.0.0] - 2020-07-03 8 | ### Added 9 | - Start using "changelog" 10 | - Added ncurses to handle terminal interaction 11 | - Added new public functions to handle IO (ie: printf, println); 12 | 13 | ### Changed 14 | 15 | ### Removed 16 | - Removed support for iostream. All terminal IO interactions must be done using Ginseng own functions. -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Ginseng.h" 3 | 4 | int main() 5 | { 6 | Ginseng repl( 7 | "$test>", 8 | [&repl]() { 9 | repl.println("WELCOME TO MY AWESOME RELP!"); 10 | repl.println("Type \"help\" to start"); 11 | repl.println(""); 12 | repl.println("HAVE FUN!"); 13 | }, 14 | [&repl]() { 15 | repl.println("BYE!"); 16 | }); 17 | 18 | // Create Help struct for hello command 19 | Help hello_h("Says hello back at you", "[name]"); 20 | 21 | // Add command to the REPL 22 | repl.add_command( 23 | "hello", 24 | [&repl](std::vector args) -> int { 25 | if (args.size() < 2) 26 | return Exit::INVALID_ARGUMENTS; 27 | repl.printf("HELLO %s\n", args[1].c_str()); 28 | return Exit::SUCCESS; 29 | }, 30 | hello_h); 31 | 32 | repl.start(); 33 | return 0; 34 | } -------------------------------------------------------------------------------- /media/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chewax/Ginseng/17091edee4bdfba5a567ccc4611585b81e9abc28/media/logo.png -------------------------------------------------------------------------------- /media/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | 13 | 15 | 17 | 21 | 25 | 27 | 35 | 36 | 37 | 38 | 44 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /media/sshot.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chewax/Ginseng/17091edee4bdfba5a567ccc4611585b81e9abc28/media/sshot.1.png -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | Logo 5 | 6 |

7 | 8 |
9 | 10 | [![Contributors][contributors-shield]][contributors-url] 11 | [![Issues][issues-shield]][issues-url] 12 | [![Build Status](https://travis-ci.org/chewax/Ginseng.svg?branch=master)](https://travis-ci.org/chewax/Ginseng) 13 | [![Last Commit][last-commit-shield]][last-commit-url] 14 | [![MIT License][license-shield]][license-url] 15 | 16 | 17 | 18 | 19 | ## Table of Contents 20 | 21 | * [About the Project](#about-the-project) 22 | * [Getting Started](#getting-started) 23 | * [Usage](#usage) 24 | * [Roadmap](#roadmap) 25 | * [Contributing](#contributing) 26 | * [License](#license) 27 | * [Contact](#contact) 28 | 29 | 30 | 31 | 32 | ## About The Project 33 | 34 | ![Ginseng](media/sshot.1.png) 35 | 36 | This is a lightweight header only library that will help you build REPL tools faster. It is based on the **ncurses** library. 37 | Before proceeding with installation please make sure you have this library installed. 38 | 39 | 40 | 41 | ## Getting Started 42 | 43 | To get a local copy up and running follow these simple steps. 44 | 45 | ### Prerequisites 46 | 47 | 1. c++11 48 | 2. ncurses 49 | 50 | 51 | ### Installation 52 | 53 | 1. Clone the Ginseng into repo into your libs 54 | 55 | ```sh 56 | git clone https://github.com/chewax/Ginseng.git 57 | ``` 58 | 59 | 60 | ## Usage 61 | 62 | ### Basic usage. 63 | 64 | ```c++ 65 | #include "Ginseng.h" 66 | 67 | int main() 68 | { 69 | Ginseng repl; 70 | repl.start(); 71 | return 0; 72 | } 73 | ``` 74 | 75 | This example will setup a basic REPL tool with empty commands. At this stage you can use commands such as ``help`` or ``exit``. 76 | 77 | ### Configuring Delimiter. 78 | 79 | You can setup your own delimiter using the first parameter for such thing. 80 | 81 | ```c++ 82 | #include "Ginseng.h" 83 | 84 | int main() 85 | { 86 | Ginseng repl("$delim>"); 87 | repl.start(); 88 | return 0; 89 | } 90 | ``` 91 | 92 | ### Configuring custom greet and farewell functions. 93 | 94 | Ginseng will let you handle certain events in your REPL. Such is the case of (obviously) commands. But also you can set up handlers for greet and goodbye if you wish. 95 | 96 | ```c++ 97 | #include "Ginseng.h" 98 | 99 | int main() 100 | { 101 | 102 | Ginseng repl("$test>", 103 | [&repl]() { 104 | repl.println("WELCOME TO MY AWESOME RELP!"); 105 | repl.println("Type \"help\" to start"); 106 | repl.println(""); 107 | repl.println("HAVE FUN!"); 108 | }, 109 | [&repl]() { 110 | repl.println("BYE!"); 111 | }); 112 | repl.start(); 113 | return 0; 114 | } 115 | ``` 116 | 117 | ### Setting up commands. 118 | 119 | Commands can be created using ``add_command`` function. 120 | Such function receives 3 paramenters 121 | Namely: 122 | 123 | 1. Command Name 124 | 2. Command Handler (or Callback) 125 | 3. Command Help Struct 126 | 127 | Help struct is used to let Ginseng know how to print help information. 128 | Help struct is just 2 strings one for the argument list and one for the actual description. 129 | 130 | ``` 131 | // Help(std::string desc, std::string args); 132 | Help hello_help("Says hello back at you", "[name]"); 133 | ``` 134 | 135 | Callback function will be called passing a vector contining the list of arguments (including the command name) collected from the console. 136 | Vector will contain at least 1 element (namely: the command name). 137 | 138 | Callback function is required to return a success/fail return type Exit. 139 | Possible values are 140 | 141 | ``` 142 | [ SUCCESS|INVALID_ARGUMENTS|ERROR ] 143 | //eg: Exit::SUCCESS 144 | ``` 145 | This is important to let Ginseng know of the result of the command. 146 | 147 | 148 | **Here is the final code for a more advanced setup with "Hello" Command:** 149 | 150 | ```c++ 151 | #include "Ginseng.h" 152 | 153 | int main() 154 | { 155 | //Create Ginseng REPL 156 | Ginseng repl( 157 | "$test>", 158 | [&repl]() { 159 | repl.println("WELCOME TO MY AWESOME RELP!"); 160 | repl.println("Type \"help\" to start"); 161 | repl.println(""); 162 | repl.println("HAVE FUN!"); 163 | }, 164 | [&repl]() { 165 | repl.println("BYE!"); 166 | }); 167 | 168 | // Create Help struct for hello command 169 | Help hello_help("Says hello back at you", "[name]"); 170 | 171 | // Add "hello" command to the REPL 172 | repl.add_command( 173 | "hello", 174 | [&repl](std::vector args) -> int { 175 | if (args.size() < 2) 176 | return Exit::INVALID_ARGUMENTS; 177 | repl.printf("HELLO %s\n", args[1].c_str()); 178 | return Exit::SUCCESS; 179 | }, 180 | hello_help); 181 | 182 | repl.start(); 183 | return 0; 184 | } 185 | ``` 186 | 187 | 188 | 189 | ## Roadmap 190 | 191 | See the [open issues](https://github.com/chewax/Ginseng/issues) for a list of proposed features (and known issues). 192 | 193 | 194 | 195 | 196 | 197 | ## Contributing 198 | 199 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 200 | 201 | 1. Fork the Project 202 | 2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`) 203 | 3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`) 204 | 4. Push to the Branch (`git push origin feature/AmazingFeature`) 205 | 5. Open a Pull Request 206 | 207 | 208 | 209 | 210 | ## License 211 | 212 | Distributed under the MIT License. See `LICENSE` for more information. 213 | 214 | 215 | 216 | 217 | ## Contact 218 | 219 | [![LinkedIn][linkedin-shield]][linkedin-url] 220 | ![Twitter Follow](https://img.shields.io/twitter/follow/dwaksman?label=Follow&style=social) 221 | Project Link: [https://github.com/chewax/Ginseng](https://github.com/chewax/Ginseng) 222 | 223 | 224 | 225 | 226 | [contributors-shield]: https://img.shields.io/github/contributors/chewax/Ginseng.svg 227 | [contributors-url]: https://github.com/chewax/Ginseng/graphs/contributors 228 | [forks-shield]: https://img.shields.io/github/forks/chewax/Ginseng.svg 229 | [forks-url]: https://github.com/chewax/Ginseng/network/members 230 | [stars-shield]: https://img.shields.io/github/stars/chewax/Ginseng.svg 231 | [stars-url]: https://github.com/chewax/Ginseng/stargazers 232 | [issues-shield]: https://img.shields.io/github/issues/chewax/Ginseng.svg 233 | [issues-url]: https://github.com/chewax/Ginseng/issues 234 | [license-shield]: https://img.shields.io/github/license/chewax/Ginseng.svg 235 | [license-url]: https://github.com/chewax/Ginseng/blob/master/LICENSE.txt 236 | [linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?&logo=linkedin&colorB=555 237 | [linkedin-url]: https://linkedin.com/in/dwaksman 238 | [product-screenshot]: images/screenshot.png 239 | [last-commit-shield]: https://img.shields.io/github/last-commit/chewax/Ginseng 240 | [last-commit-url]: https://github.com/last-commit/chewax/Ginseng 241 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | 3 | add_executable(libtest tests.cpp) 4 | target_compile_features(libtest PRIVATE cxx_lambdas) 5 | -------------------------------------------------------------------------------- /tests/tests.cpp: -------------------------------------------------------------------------------- 1 | #define BOOST_TEST_MODULE GinsengTEST 2 | #include 3 | 4 | BOOST_AUTO_TEST_CASE(Test1) 5 | { 6 | BOOST_CHECK_EQUAL(1,1); 7 | } 8 | 9 | --------------------------------------------------------------------------------