Initial commit
This commit is contained in:
commit
6fbc93e12e
13 changed files with 652 additions and 0 deletions
89
.gitignore
vendored
Normal file
89
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
# Created by https://www.gitignore.io/api/git,linux,macos,cmake,windows,visualstudiocode
|
||||||
|
|
||||||
|
### CMake ###
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles
|
||||||
|
CMakeScripts
|
||||||
|
Testing
|
||||||
|
Makefile
|
||||||
|
cmake_install.cmake
|
||||||
|
install_manifest.txt
|
||||||
|
compile_commands.json
|
||||||
|
CTestTestfile.cmake
|
||||||
|
build
|
||||||
|
|
||||||
|
### Git ###
|
||||||
|
*.orig
|
||||||
|
|
||||||
|
### Linux ###
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
### macOS ###
|
||||||
|
*.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
### VisualStudioCode ###
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.history
|
||||||
|
|
||||||
|
### Windows ###
|
||||||
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
ehthumbs.db
|
||||||
|
ehthumbs_vista.db
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
Desktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
# End of https://www.gitignore.io/api/git,linux,macos,cmake,windows,visualstudiocode
|
||||||
8
.vscode/settings.json
vendored
Normal file
8
.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"iostream": "cpp"
|
||||||
|
},
|
||||||
|
"cSpell.words": [
|
||||||
|
"stoi"
|
||||||
|
]
|
||||||
|
}
|
||||||
57
.vscode/tasks.json
vendored
Normal file
57
.vscode/tasks.json
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
{
|
||||||
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
|
// for the documentation about the tasks.json format
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "Build development",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "./builder debug",
|
||||||
|
"problemMatcher": [
|
||||||
|
"$gcc"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"focus": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Build porduction",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "./builder release",
|
||||||
|
"problemMatcher": [
|
||||||
|
"$gcc"
|
||||||
|
],
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"focus": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Package",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "./builder package",
|
||||||
|
"problemMatcher": [
|
||||||
|
"$gcc"
|
||||||
|
],
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"focus": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Clean",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "./builder clean",
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"focus": true
|
||||||
|
},
|
||||||
|
"problemMatcher": [],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
37
CMakeLists.txt
Normal file
37
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
cmake_minimum_required(VERSION 3.9)
|
||||||
|
|
||||||
|
set(VERSION "1.0.1")
|
||||||
|
set(RELEASE, 1)
|
||||||
|
set(PACKAGE_NAME "mktouch")
|
||||||
|
set(VENDOR "AA")
|
||||||
|
set(DESCRIPTION "Make directory's and files at the same time")
|
||||||
|
|
||||||
|
set(CPACK_PACKAGE_CONTACT "Ade Attwood")
|
||||||
|
|
||||||
|
project(${PACKAGE_NAME})
|
||||||
|
|
||||||
|
add_subdirectory (src)
|
||||||
|
|
||||||
|
add_executable(mktouch ./src/App.cpp
|
||||||
|
./src/Cli.cpp
|
||||||
|
./src/main.cpp)
|
||||||
|
|
||||||
|
FIND_PACKAGE(Boost COMPONENTS program_options filesystem REQUIRED)
|
||||||
|
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
TARGET_LINK_LIBRARIES(mktouch ${Boost_LIBRARIES})
|
||||||
|
|
||||||
|
set(CPACK_PACKAGE_VERSION ${VERSION})
|
||||||
|
set(CPACK_GENERATOR "DEB;ZIP;TGZ")
|
||||||
|
set(CPACK_PACKAGE_NAME ${PACKAGE_NAME})
|
||||||
|
set(CPACK_PACKAGE_RELEASE ${RELEASE})
|
||||||
|
set(CPACK_PACKAGE_VENDOR ${VENDOR})
|
||||||
|
set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
|
||||||
|
set(CPACK_PACKAGE_DESCRIPTION ${DESCRIPTION})
|
||||||
|
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libboost-program-options1.62.0,libboost-filesystem1.62.0,libboost-system1.62.0,libstdc++6,libgcc1,libc6")
|
||||||
|
|
||||||
|
install(TARGETS mktouch DESTINATION bin)
|
||||||
|
install(DIRECTORY man DESTINATION .)
|
||||||
|
|
||||||
|
include(CPack)
|
||||||
6
apt-pkg.txt
Normal file
6
apt-pkg.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
libboost-filesystem1.62.0
|
||||||
|
libboost-program-options1.62.0
|
||||||
|
libboost-system1.62.0
|
||||||
|
libc6
|
||||||
|
libgcc1
|
||||||
|
libstdc++6
|
||||||
64
builder
Executable file
64
builder
Executable file
|
|
@ -0,0 +1,64 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
SRC_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)";
|
||||||
|
|
||||||
|
DEBUG_DIR="$SRC_DIR/build/Debug";
|
||||||
|
RELEASE_DIR="$SRC_DIR/build/Release";
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
apt-pkg)
|
||||||
|
ldd build/Release/mktouch | awk '/=>/{print $(NF-1)}' | while read n; do dpkg-query -S $n | cut -d ":" -f 1; done | uniq | sort > apt-pkg.txt;
|
||||||
|
;;
|
||||||
|
debug)
|
||||||
|
echo "CMAKE --> Debug";
|
||||||
|
mkdir -p "$DEBUG_DIR";
|
||||||
|
cd "$DEBUG_DIR";
|
||||||
|
BUILD_TYPE="Debug";
|
||||||
|
BUILD="true";
|
||||||
|
MAKE="true";
|
||||||
|
;;
|
||||||
|
release)
|
||||||
|
echo "CMAKE --> Release";
|
||||||
|
mkdir -p "$RELEASE_DIR";
|
||||||
|
cd "$RELEASE_DIR";
|
||||||
|
BUILD_TYPE="Release";
|
||||||
|
BUILD="true";
|
||||||
|
MAKE="true";
|
||||||
|
;;
|
||||||
|
package)
|
||||||
|
echo "CMAKE --> Release";
|
||||||
|
mkdir -p "$RELEASE_DIR";
|
||||||
|
cd "$RELEASE_DIR";
|
||||||
|
BUILD_TYPE="Release";
|
||||||
|
BUILD="true";
|
||||||
|
MAKE="true";
|
||||||
|
PACKAGE="true";
|
||||||
|
;;
|
||||||
|
clean)
|
||||||
|
echo "CMAKE --> Cleaning";
|
||||||
|
rm -rf "$SRC_DIR/build";
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "CMAKE --> Build not found";
|
||||||
|
echo " -- apt-pkg";
|
||||||
|
echo " -- debug";
|
||||||
|
echo " -- release";
|
||||||
|
echo " -- clean";
|
||||||
|
exit 0;
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -n "$BUILD" ]; then
|
||||||
|
cp -R $SRC_DIR/man $(pwd);
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE $SRC_DIR;
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$MAKE" ]; then
|
||||||
|
echo "CMAKE --> Make";
|
||||||
|
make;
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$PACKAGE" ]; then
|
||||||
|
echo "CMAKE --> Package";
|
||||||
|
make package;
|
||||||
|
fi
|
||||||
36
man/man1/mktouch.1
Normal file
36
man/man1/mktouch.1
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
|
||||||
|
.TH mkdir 1 "03 feb 2018" "Version 1.0.1" "mktouch man page"
|
||||||
|
.SH NAME
|
||||||
|
mktouch \- Make directory's and files at the same time
|
||||||
|
.SH SYNOPSIS
|
||||||
|
mktouch
|
||||||
|
.I file-path file
|
||||||
|
[options]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
Make directory's and files at the same time.
|
||||||
|
.SH OPTIONS
|
||||||
|
.PP
|
||||||
|
-f [ --force ] Force create the file even if it exsits
|
||||||
|
.PP
|
||||||
|
-h [ --help ] Show the help message
|
||||||
|
.PP
|
||||||
|
-V [ --version ] Display the version number
|
||||||
|
.SH EXAMPLES
|
||||||
|
.PP
|
||||||
|
.B mktouch /my/path
|
||||||
|
.RE
|
||||||
|
This command will just create the dir /my/path just like the mkdir command
|
||||||
|
.PP
|
||||||
|
.B mktouch /my/path file.txt
|
||||||
|
.RE
|
||||||
|
This will make the path like above and then create the file `file.txt` and put it into the directory
|
||||||
|
.PP
|
||||||
|
.B mktouch /my/path file.txt -f
|
||||||
|
.RE
|
||||||
|
This will do the same as above but if the file already exsits it will be overriten
|
||||||
|
.SH SEE ALSO
|
||||||
|
mkdir(1) touch(1)
|
||||||
|
.SH BUGS
|
||||||
|
No known bugs.
|
||||||
|
.SH AUTHOR
|
||||||
|
Ade Attwood (code@adeattwood.co.uk)
|
||||||
107
src/App.cpp
Normal file
107
src/App.cpp
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
|
#include "App.h"
|
||||||
|
#include "Cli.h"
|
||||||
|
|
||||||
|
App::App() {}
|
||||||
|
App::App(const App& orig) {}
|
||||||
|
App::~App() {}
|
||||||
|
|
||||||
|
int App::shutDown(int code) {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::parseArgs(int argc, char** argv) {
|
||||||
|
namespace po = boost::program_options;
|
||||||
|
|
||||||
|
po::options_description options("Options");
|
||||||
|
options.add_options()
|
||||||
|
("force,f", "Force create the file even if it exsits")
|
||||||
|
("help,h", "Show this messages")
|
||||||
|
("version,V", "Display the version number");
|
||||||
|
|
||||||
|
po::options_description arguments("Arguments");
|
||||||
|
arguments.add_options()
|
||||||
|
("file-path", po::value<std::string>(), "The path where to create the file")
|
||||||
|
("file", po::value<std::string>(), "The file to create");
|
||||||
|
|
||||||
|
positionalOptions.add("file-path", 1);
|
||||||
|
positionalOptions.add("file", 1);
|
||||||
|
|
||||||
|
desc.add(arguments).add(options);
|
||||||
|
|
||||||
|
po::store(po::command_line_parser(argc, argv).
|
||||||
|
positional(positionalOptions).
|
||||||
|
options(desc).
|
||||||
|
run(),
|
||||||
|
vm);
|
||||||
|
|
||||||
|
po::notify(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::showHelp() {
|
||||||
|
std::vector<std::string> parts;
|
||||||
|
|
||||||
|
parts.push_back("Usage: ");
|
||||||
|
parts.push_back(this->name);
|
||||||
|
|
||||||
|
size_t N = positionalOptions.max_total_count();
|
||||||
|
|
||||||
|
if (N == std::numeric_limits<unsigned>::max()) {
|
||||||
|
std::vector<std::string> args = this->_getUnlimitedPositionalArgs(positionalOptions);
|
||||||
|
parts.insert(parts.end(), args.begin(), args.end());
|
||||||
|
} else {
|
||||||
|
for(size_t i = 0; i < N; ++i) {
|
||||||
|
parts.push_back(positionalOptions.name_for_position(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desc.options().size() > 0) {
|
||||||
|
parts.push_back("[options]");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
std::copy(parts.begin(), parts.end(), std::ostream_iterator<std::string>(oss, " "));
|
||||||
|
oss << '\n' << desc;
|
||||||
|
|
||||||
|
std::cout << Cli::style(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> App::_getUnlimitedPositionalArgs(const po::positional_options_description& p)
|
||||||
|
{
|
||||||
|
assert(p.max_total_count() == std::numeric_limits<unsigned>::max());
|
||||||
|
|
||||||
|
std::vector<std::string> parts;
|
||||||
|
|
||||||
|
const int MAX = 1000;
|
||||||
|
std::string last = p.name_for_position(MAX);
|
||||||
|
|
||||||
|
for (size_t i = 0; true; ++i) {
|
||||||
|
std::string cur = p.name_for_position(i);
|
||||||
|
if (cur == last) {
|
||||||
|
parts.push_back(cur);
|
||||||
|
parts.push_back('[' + cur + ']');
|
||||||
|
parts.push_back("...");
|
||||||
|
return parts;
|
||||||
|
}
|
||||||
|
parts.push_back(cur);
|
||||||
|
}
|
||||||
|
return parts; // never get here
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::showVersion() {
|
||||||
|
std::cout << "Version: " << this->version << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool App::hasOption(std::string name) {
|
||||||
|
return vm.count(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
po::variable_value App::getOption(std::string name) {
|
||||||
|
return vm[name];
|
||||||
|
}
|
||||||
|
|
||||||
39
src/App.h
Normal file
39
src/App.h
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
#ifndef APP_H
|
||||||
|
#define APP_H
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
|
namespace po = boost::program_options;
|
||||||
|
|
||||||
|
class App {
|
||||||
|
po::variables_map vm;
|
||||||
|
po::options_description desc;
|
||||||
|
po::positional_options_description positionalOptions;
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::string version = "1.0.1";
|
||||||
|
std::string name = "mktouch";
|
||||||
|
|
||||||
|
App();
|
||||||
|
App(const App& orig);
|
||||||
|
virtual ~App();
|
||||||
|
|
||||||
|
void parseArgs(int argc, char** argv);
|
||||||
|
|
||||||
|
void showHelp();
|
||||||
|
void showVersion();
|
||||||
|
bool hasOption(std::string name);
|
||||||
|
int shutDown(int code);
|
||||||
|
|
||||||
|
po::variable_value getOption(std::string name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::string> _getUnlimitedPositionalArgs(const po::positional_options_description& p);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* APP_H */
|
||||||
|
|
||||||
0
src/CMakeLists.txt
Normal file
0
src/CMakeLists.txt
Normal file
119
src/Cli.cpp
Normal file
119
src/Cli.cpp
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "Cli.h"
|
||||||
|
|
||||||
|
Cli::Cli() {}
|
||||||
|
Cli::Cli(const Cli& orig) {}
|
||||||
|
Cli::~Cli() {}
|
||||||
|
|
||||||
|
std::string Cli::style(std::string string) {
|
||||||
|
|
||||||
|
Cli::replace(string, "{{eol}}", "\n");
|
||||||
|
|
||||||
|
Cli::replace(string, "{{", "\e[");
|
||||||
|
Cli::replace(string, "}}", "m");
|
||||||
|
|
||||||
|
Cli::replace(string, "cli_fg_red", "31");
|
||||||
|
Cli::replace(string, "cli_fg_default", "39");
|
||||||
|
Cli::replace(string, "cli_fg_green", "32");
|
||||||
|
Cli::replace(string, "cli_fg_yellow", "33");
|
||||||
|
Cli::replace(string, "cli_fg_blue", "34");
|
||||||
|
Cli::replace(string, "cli_fg_white", "97");
|
||||||
|
Cli::replace(string, "cli_fg_black", "30");
|
||||||
|
|
||||||
|
Cli::replace(string, "cli_bg_red", "41");
|
||||||
|
Cli::replace(string, "cli_bg_default", "49");
|
||||||
|
Cli::replace(string, "cli_bg_green", "42");
|
||||||
|
Cli::replace(string, "cli_bg_yellow", "43");
|
||||||
|
Cli::replace(string, "cli_bg_blue", "44");
|
||||||
|
Cli::replace(string, "cli_bg_white", "107");
|
||||||
|
Cli::replace(string, "cli_bg_black", "40");
|
||||||
|
|
||||||
|
Cli::replace(string, "cli_reset_normal", "0");
|
||||||
|
Cli::replace(string, "cli_reset_bold", "21");
|
||||||
|
Cli::replace(string, "cli_reset_dim", "22");
|
||||||
|
Cli::replace(string, "cli_reset_underline", "24");
|
||||||
|
Cli::replace(string, "cli_reset_blink", "25");
|
||||||
|
Cli::replace(string, "cli_reset_invert", "27");
|
||||||
|
Cli::replace(string, "cli_reset_hidden", "28");
|
||||||
|
|
||||||
|
Cli::replace(string, "cli_normal", "0");
|
||||||
|
Cli::replace(string, "cli_bold", "1");
|
||||||
|
Cli::replace(string, "cli_dim", "2");
|
||||||
|
Cli::replace(string, "cli_underline", "4");
|
||||||
|
Cli::replace(string, "cli_blink", "5");
|
||||||
|
Cli::replace(string, "cli_invert", "7");
|
||||||
|
Cli::replace(string, "cli_hidden", "8");
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Cli::replace(std::string& str, const std::string& from, const std::string& to) {
|
||||||
|
if(from.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t start_pos = 0;
|
||||||
|
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
|
||||||
|
str.replace(start_pos, from.length(), to);
|
||||||
|
start_pos += to.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cli::out(std::string output) {
|
||||||
|
std::cout << Cli::style(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cli::hideCursor() {
|
||||||
|
Cli::out("\033[?25l");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cli::showCursor() {
|
||||||
|
Cli::out("\033[?25h");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cli::clearScreen() {
|
||||||
|
Cli::out("\033[2J");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cli::clearLine() {
|
||||||
|
Cli::out("\033[2K");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Cli::in() {
|
||||||
|
std::string out;
|
||||||
|
std::cin >> out;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Cli::readLine(std::string question) {
|
||||||
|
Cli::out(question);
|
||||||
|
return Cli::in();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Cli::askQuestion(std::string question, std::map <int, std::string> questionOptions) {
|
||||||
|
question += "{{eol}}";
|
||||||
|
|
||||||
|
for (const auto& kv : questionOptions) {
|
||||||
|
question += "[" + std::to_string(kv.first) + "] " + kv.second + "{{eol}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string out;
|
||||||
|
|
||||||
|
while (out.empty()) {
|
||||||
|
std::string answer = Cli::readLine(question);
|
||||||
|
|
||||||
|
if (questionOptions.find(std::stoi(answer)) == questionOptions.end()) {
|
||||||
|
Cli::out("Invalid option{{eol}}");
|
||||||
|
} else {
|
||||||
|
out = answer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::stoi(out);
|
||||||
|
}
|
||||||
31
src/Cli.h
Normal file
31
src/Cli.h
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
|
||||||
|
#ifndef CLI_H
|
||||||
|
#define CLI_H
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
class Cli {
|
||||||
|
public:
|
||||||
|
Cli();
|
||||||
|
Cli(const Cli& orig);
|
||||||
|
virtual ~Cli();
|
||||||
|
|
||||||
|
static void out(std::string output);
|
||||||
|
static std::string in();
|
||||||
|
static void hideCursor();
|
||||||
|
static void showCursor();
|
||||||
|
static void clearScreen();
|
||||||
|
static void clearLine();
|
||||||
|
|
||||||
|
static std::string readLine(std::string question);
|
||||||
|
static int askQuestion(std::string qustion, std::map < int, std::string >);
|
||||||
|
static std::string style(std::string string);
|
||||||
|
private:
|
||||||
|
static bool replace(std::string& str, const std::string& from, const std::string& to);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* CLI_H */
|
||||||
|
|
||||||
59
src/main.cpp
Normal file
59
src/main.cpp
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
#include "App.h"
|
||||||
|
#include "Cli.h"
|
||||||
|
|
||||||
|
namespace fs = boost::filesystem;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const size_t SUCCESS = 0;
|
||||||
|
const size_t ERROR = 1;
|
||||||
|
const size_t UNHANDLED_ERROR = 2;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
App app;
|
||||||
|
|
||||||
|
try {
|
||||||
|
app.parseArgs(argc, argv);
|
||||||
|
} catch(std::exception& E) {
|
||||||
|
std::cout << "ERROR: " << E.what() << std::endl;
|
||||||
|
return app.shutDown(UNHANDLED_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app.hasOption("help")) {
|
||||||
|
app.showHelp();
|
||||||
|
return app.shutDown(SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app.hasOption("version")) {
|
||||||
|
app.showVersion();
|
||||||
|
return app.shutDown(SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!app.hasOption("file-path")) {
|
||||||
|
app.showHelp();
|
||||||
|
return app.shutDown(ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string filePath = app.getOption("file-path").as<std::string>();
|
||||||
|
fs::create_directories(filePath);
|
||||||
|
|
||||||
|
if (app.hasOption("file")) {
|
||||||
|
std::string file = filePath + "/" + app.getOption("file").as<std::string>();
|
||||||
|
|
||||||
|
if (!app.hasOption("force") && fs::exists(file)) {
|
||||||
|
std::cout << "ERROR: " << file << " already exists" << std::endl;
|
||||||
|
return app.shutDown(ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ofstream outfile (file);
|
||||||
|
outfile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return app.shutDown(SUCCESS);
|
||||||
|
};
|
||||||
Loading…
Reference in a new issue