Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft CLI tool #1

Draft
wants to merge 21 commits into
base: master
Choose a base branch
from
15 changes: 15 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.1)
project(jinja2cpp-cli CXX)

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()


add_library(jinja2cpp-libcli src/command_line.cpp src/command_line.h)

add_executable(${PROJECT_NAME} src/main.cpp)
target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS} jinja2cpp-libcli)

# Setup testing
enable_testing()
add_subdirectory(test)
38 changes: 38 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
FROM alpine:latest as builder

LABEL maintainer="Andrey Bronin <jonnib@yandex.ru>"

RUN apk update && \
apk upgrade && \
apk --update add \
# alpine-sdk \
g++ \
build-base \
cmake \
# bash \
libstdc++ \
git \
linux-headers \
# cppcheck \
py-pip && \
pip install conan && \
rm -rf /var/cache/apk/*

COPY . /project
WORKDIR /project
RUN conan user
RUN conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan
RUN conan remote add andreybronin https://api.bintray.com/conan/andreybronin/conan
RUN conan remote add martinmoene https://api.bintray.com/conan/martinmoene/nonstd-lite
RUN conan install . --build=missing
RUN cmake -DCMAKE_BUILD_TYPE=Release . && make

FROM alpine:latest
COPY --from=builder /project/bin/jinja2cpp-cli /jinja2cpp

RUN apk update && \
apk upgrade && \
apk --update add libstdc++ \
rm -rf /var/cache/apk/*

ENTRYPOINT [ "/jinja2cpp" ]
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,11 @@
# tools-cli
# Jinja2cpp CLI tool

```
Usage: jinja2cpp [options] <input template> <input data>
Options:
-h [ --help ] Display this help message
-v [ --version ] Display the version number
--format Format of input variables: auto, ini, json
--input-template arg Input template file path
--input-data arg Define template variable in the form of key=value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also '--templates-dir' option needed in order to properly setup TemplateEnv and templates inheritance/inclusion support.

```
7 changes: 7 additions & 0 deletions conanfile.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[requires]
jinja2cpp/master@andreybronin/testing
rapidjson/1.1.0@bincrafters/stable
gtest/1.8.1@bincrafters/stable

[generators]
cmake
104 changes: 104 additions & 0 deletions src/command_line.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#include "command_line.h"

#include <boost/program_options.hpp>
#include <rapidjson/document.h>

#include <iostream>
#include <memory>

namespace jinja2
{

CommandLine::CommandLine(std::unique_ptr<Template> tpl) : m_tpl(std::move(tpl)) { }

int CommandLine::Execute(int argc, char **argv)
{
namespace po = boost::program_options;
po::options_description desc("Options");

desc.add_options()
("help,h", "Display this help message")
("version,v", "Display the version number")
("format", "Format of input variables: auto, ini, json")
("input-template", po::value<std::vector<std::string>>(), "Input template file path")
("input-data", po::value<std::vector<std::string>>(),
"Define template variable in the form of key=value");

po::positional_options_description p;
p.add("input-template", 1);
p.add("input-data", -1);

try {
po::variables_map vm;
po::store(po::command_line_parser(argc, argv).options(desc).positional(p).allow_unregistered().run(), vm);
po::notify(vm);

if (vm.count("help")) {
std::cout << Help() << std::endl << desc << std::endl;
return EXIT_FAILURE;
}

if (vm.count("version")) {
std::cout << Version() << std::endl;
return EXIT_SUCCESS;
}

// for (auto &v : vm["input-data"].as<std::vector<std::string> >())
// {
// if (vm.count("input-data")) {
// std::cout << "Input data are: ";
// std::cout << v << std::endl;
// }
// }


if (vm.count("input-template"))
{
const auto &filename = vm["input-template"].as<std::vector<std::string> >()[0];
RenderTemplate(filename);
return EXIT_SUCCESS;
}

}
catch (std::exception const& e)
{
std::cerr << e.what() << std::endl;
}
return EXIT_FAILURE;
}

std::string CommandLine::Help()
{
return "Usage: jinja2cpp [options] <input template> <input data>";
}

std::string CommandLine::Version()
{
// TODO: get jinja2cpp version
return "unknown";
}


void CommandLine::RenderTemplate(const std::string& fileName)
{
jinja2::Template tpl;
auto result = tpl.LoadFromFile(fileName);
if (!result.has_value()) {
std::cout << result.error() << std::endl;
}

std::cout << "Input template is: ";
std::cout << fileName << std::endl;

tpl.Render(std::cout, {});
}

void parceOptions() {
rapidjson::Document document;
// document.Parse()
//
// for (auto& v : a.GetArray())
// printf("%d ", v.GetInt());
}

} // namespace jinja2
24 changes: 24 additions & 0 deletions src/command_line.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once

#include <jinja2cpp/template.h>

#include <string>

namespace jinja2 {

class CommandLine {
public:
explicit CommandLine(std::unique_ptr<Template> tpl = std::make_unique<Template>());

int Execute(int argc, char **argv);

protected:
std::string Help();
std::string Version();
void RenderTemplate(const std::string& fileName);

private:
std::unique_ptr<Template> m_tpl;
};

} // namespace jinja2
6 changes: 6 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "command_line.h"

int main(int argc, char **argv) {
jinja2::CommandLine cli;
return cli.Execute(argc, argv);
}
7 changes: 7 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 3.1)
project(test_jinja2cpp-cli CXX)

add_executable (${PROJECT_NAME} command_line_test.cpp)
target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS} jinja2cpp-libcli)

add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME} --gtest_output=xml)
58 changes: 58 additions & 0 deletions test/command_line_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include "../src/command_line.h"

#include <gtest/gtest.h>
#include <gmock/gmock.h>

using namespace testing;
using namespace jinja2;

class MockTemplate : public Template
{
public:
MOCK_METHOD2(Load, ParseResult(const char* tpl, std::string tplName));
MOCK_METHOD2(Load, ParseResult(const std::string& str, std::string tplName));
MOCK_METHOD2(Load, ParseResult(std::istream& stream, std::string tplName));

MOCK_METHOD1(LoadFromFile, ParseResult (const std::string& fileName));
MOCK_METHOD2(Render, void (std::ostream& os, const ValuesMap& params));
MOCK_METHOD1(RenderAsString, std::string (const ValuesMap& params));
};

TEST(CommandLine, Execute_without_args_expect_show_help)
{
MockTemplate tpl;
// EXPECT_CALL(tpl, Load(std::string("123"), std::string("321"))).WillOnce(Return(ParseResult{}));

//Template t = static_cast<Template>(tpl);
CommandLine cli(std::make_unique<Template>(tpl));
//auto argv = *char[2]{"sf", "qeqwe"};

ASSERT_EQ(EXIT_FAILURE, cli.Execute(1, nullptr));

}

TEST(CommandLine, Execute_help)
{
MockTemplate tpl;
// EXPECT_CALL(tpl, Load(std::string("123"), std::string("321"))).WillOnce(Return(ParseResult{}));

//Template t = static_cast<Template>(tpl);
CommandLine cli(std::make_unique<Template>(tpl));
//auto argv = *char[2]{"sf", "version"};

// TODO: expect call Version()
ASSERT_EQ(EXIT_SUCCESS, cli.Execute(1, nullptr));
}

TEST(CommandLine, Execute_version)
{
MockTemplate tpl;
// EXPECT_CALL(tpl, Load(std::string("123"), std::string("321"))).WillOnce(Return(ParseResult{}));

//Template t = static_cast<Template>(tpl);
CommandLine cli(std::make_unique<Template>(tpl));
//auto argv = *char[2]{"sf", "version"};

// TODO: expect call Version()
ASSERT_EQ(EXIT_SUCCESS, cli.Execute(1, nullptr));
}