Add --path-to-namespace option to drogon_ctl for creating views (#607)

This commit is contained in:
An Tao 2020-10-12 21:51:39 +08:00 committed by GitHub
parent c264c91f38
commit 43e7b3fec0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 220 additions and 92 deletions

View File

@ -47,6 +47,7 @@ else(BUILD_DROGON_SHARED)
add_library(${PROJECT_NAME} STATIC)
endif(BUILD_DROGON_SHARED)
include(cmake/DrogonUtilities.cmake)
include(CheckIncludeFileCXX)
check_include_file_cxx(any HAS_ANY)
@ -456,6 +457,7 @@ install(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/Findpg.cmake"
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/FindBrotli.cmake"
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/Findcoz-profiler.cmake"
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/DrogonUtilities.cmake"
DESTINATION "${INSTALL_DROGON_CMAKE_DIR}"
COMPONENT dev)

View File

@ -0,0 +1,60 @@
# ##############################################################################
# function drogon_create_views(target source_path output_path
# [use_path_as_namespace])
# ##############################################################################
function(drogon_create_views arg)
if(ARGC LESS 3)
message(STATUS "arguments error when calling drogon_create_views")
return()
endif()
file(MAKE_DIRECTORY ${ARGV2})
file(GLOB_RECURSE SCP_LIST ${ARGV1}/*.csp)
foreach(cspFile ${SCP_LIST})
file(RELATIVE_PATH
inFile
${CMAKE_CURRENT_SOURCE_DIR}
${cspFile})
if(ARGC GREATER 3 AND ARGV3)
string(REPLACE "/"
"_"
f1
${inFile})
string(REPLACE "\\"
"_"
f2
${f1})
string(REPLACE ".csp"
""
outputFile
${f2})
add_custom_command(OUTPUT ${ARGV2}/${outputFile}.h ${ARGV2}/${outputFile}.cc
COMMAND drogon_ctl
ARGS
create
view
${inFile}
--path-to-namespace
-o
${ARGV2}
DEPENDS ${cspFile}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
VERBATIM)
set(VIEWSRC ${VIEWSRC} ${ARGV2}/${outputFile}.cc)
else()
get_filename_component(classname ${cspFile} NAME_WE)
add_custom_command(OUTPUT ${ARGV2}/${classname}.h ${ARGV2}/${classname}.cc
COMMAND drogon_ctl
ARGS
create
view
${inFile}
-o
${ARGV2}
DEPENDS ${cspFile}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
VERBATIM)
set(VIEWSRC ${VIEWSRC} ${ARGV2}/${classname}.cc)
endif()
endforeach()
target_sources(${ARGV0} PRIVATE ${VIEWSRC})
endfunction(drogon_create_views)

View File

@ -42,6 +42,7 @@ endif()
get_filename_component(DROGON_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
if(NOT TARGET Drogon::Drogon)
include("${DROGON_CMAKE_DIR}/DrogonTargets.cmake")
include("${DROGON_CMAKE_DIR}/DrogonUtilities.cmake")
endif()
get_target_property(DROGON_INCLUDE_DIRS Drogon::Drogon INTERFACE_INCLUDE_DIRECTORIES)

View File

@ -1,7 +1,7 @@
/**
*
* create.cc
* An Tao
* @file create.cc
* @author An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
@ -24,7 +24,8 @@ std::string create::detail()
"Usage:drogon_ctl create <view|controller|filter|project|model> "
"[-options] <object name>\n\n"
"drogon_ctl create view <csp file name> [-o <output path>] [-n "
"<namespace>]//create HttpView source files from csp files\n\n"
"<namespace>]|[--path-to-namespace]//create HttpView source files "
"from csp files\n\n"
"drogon_ctl create controller [-s] <[namespace::]class_name> //"
"create HttpSimpleController source files\n\n"
"drogon_ctl create controller -h <[namespace::]class_name> //"

View File

@ -1,7 +1,7 @@
/**
*
* create_view.cc
* An Tao
* @file create_view.cc
* @author An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
@ -271,6 +271,12 @@ void create_view::handleCommand(std::vector<std::string> &parameters)
}
continue;
}
else if (file == "--path-to-namespace")
{
iter = parameters.erase(iter);
pathToNamespaceFlag_ = true;
continue;
}
else if (file[0] == '-')
{
std::cout << ARGS_ERROR_STR << std::endl;
@ -292,6 +298,42 @@ int create_view::createViewFile(const std::string &script_filename)
{
std::cout << "create HttpView Class file by " << script_filename
<< std::endl;
if (pathToNamespaceFlag_)
{
std::string::size_type pos1 = 0, pos2 = 0;
if (script_filename.length() >= 2 && script_filename[0] == '.' &&
(script_filename[1] == '/' || script_filename[1] == '\\'))
{
pos1 = pos2 = 2;
}
else if (script_filename.length() >= 1 &&
(script_filename[0] == '/' || script_filename[0] == '\\'))
{
pos1 = pos2 = 1;
}
while (pos2 < script_filename.length() - 1)
{
if (script_filename[pos2] == '/' || script_filename[pos2] == '\\')
{
if (pos2 > pos1)
{
namespaces_.push_back(
script_filename.substr(pos1, pos2 - pos1));
}
pos1 = ++pos2;
}
else
{
++pos2;
}
}
}
std::string npPrefix;
for (auto &np : namespaces_)
{
npPrefix += np;
npPrefix += "_";
}
std::ifstream infile(script_filename.c_str(), std::ifstream::in);
if (infile)
{
@ -304,8 +346,10 @@ int create_view::createViewFile(const std::string &script_filename)
className = className.substr(pos + 1);
}
std::cout << "className=" << className << std::endl;
std::string headFileName = outputPath_ + "/" + className + ".h";
std::string sourceFilename = outputPath_ + "/" + className + ".cc";
std::string headFileName =
outputPath_ + "/" + npPrefix + className + ".h";
std::string sourceFilename =
outputPath_ + "/" + npPrefix + className + ".cc";
std::ofstream oHeadFile(headFileName.c_str(), std::ofstream::out);
std::ofstream oSourceFile(sourceFilename.c_str(),
std::ofstream::out);
@ -317,7 +361,7 @@ int create_view::createViewFile(const std::string &script_filename)
}
newViewHeaderFile(oHeadFile, className);
newViewSourceFile(oSourceFile, className, infile);
newViewSourceFile(oSourceFile, className, npPrefix, infile);
}
else
return -1;
@ -335,17 +379,16 @@ void create_view::newViewHeaderFile(std::ofstream &file,
file << "//this file is generated by program automatically,don't modify "
"it!\n";
file << "#include <drogon/DrTemplate.h>\n";
file << "using namespace drogon;\n";
for (auto &np : namespaces_)
{
file << "namespace " << np << "\n";
file << "{\n";
}
file << "class " << className << ":public DrTemplate<" << className
file << "class " << className << ":public drogon::DrTemplate<" << className
<< ">\n";
file << "{\npublic:\n\t" << className << "(){};\n\tvirtual ~" << className
<< "(){};\n\t"
"virtual std::string genText(const DrTemplateData &) "
"virtual std::string genText(const drogon::DrTemplateData &) "
"override;\n};\n";
for (auto i = 0; i < namespaces_.size(); ++i)
{
@ -355,11 +398,12 @@ void create_view::newViewHeaderFile(std::ofstream &file,
void create_view::newViewSourceFile(std::ofstream &file,
const std::string &className,
const std::string &namespacePrefix,
std::ifstream &infile)
{
file << "//this file is generated by program(drogon_ctl) "
"automatically,don't modify it!\n";
file << "#include \"" << className << ".h\"\n";
file << "#include \"" << namespacePrefix << className << ".h\"\n";
file << "#include <drogon/utils/OStringStream.h>\n";
file << "#include <string>\n";
file << "#include <map>\n";
@ -372,22 +416,7 @@ void create_view::newViewSourceFile(std::ofstream &file,
file << "#include <list>\n";
file << "#include <deque>\n";
file << "#include <queue>\n";
if (!namespaces_.empty())
{
file << "using namespace ";
for (int i = 0; i < namespaces_.size(); ++i)
{
if (i != namespaces_.size() - 1)
{
file << namespaces_[i] << "::";
}
else
{
file << namespaces_[i] << ";";
}
}
file << "\n";
}
// Find layout tag
std::string layoutName;
std::regex layoutReg("<%layout[ \\t]+(((?!%\\}).)*[^ \\t])[ \\t]*%>");
@ -457,8 +486,23 @@ void create_view::newViewSourceFile(std::ofstream &file,
infile.seekg(0, std::ifstream::beg);
}
// std::cout<<"file pos:"<<infile.tellg()<<std::endl;
if (!namespaces_.empty())
{
file << "using namespace ";
for (int i = 0; i < namespaces_.size(); ++i)
{
if (i != namespaces_.size() - 1)
{
file << namespaces_[i] << "::";
}
else
{
file << namespaces_[i] << ";";
}
}
file << "\n";
}
file << "using namespace drogon;\n";
std::string viewDataName = className + "_view_data";
// virtual std::string genText(const DrTemplateData &)
file << "std::string " << className << "::genText(const DrTemplateData& "

View File

@ -1,7 +1,7 @@
/**
*
* create_view.h
* An Tao
* @file create_view.h
* @author An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
@ -31,11 +31,13 @@ class create_view : public DrObject<create_view>, public CommandHandler
protected:
std::string outputPath_{"."};
std::vector<std::string> namespaces_;
bool pathToNamespaceFlag_{false};
void createViewFiles(std::vector<std::string> &cspFileNames);
int createViewFile(const std::string &script_filename);
void newViewHeaderFile(std::ofstream &file, const std::string &className);
void newViewSourceFile(std::ofstream &file,
const std::string &className,
const std::string &namespacePrefix,
std::ifstream &infile);
};
} // namespace drogon_ctl

View File

@ -1,4 +1,4 @@
cmake_minimum_required (VERSION 3.5)
cmake_minimum_required(VERSION 3.5)
project([[ProjectName]] CXX)
include(CheckIncludeFileCXX)
@ -6,9 +6,9 @@ include(CheckIncludeFileCXX)
check_include_file_cxx(any HAS_ANY)
check_include_file_cxx(string_view HAS_STRING_VIEW)
if(HAS_ANY AND HAS_STRING_VIEW)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 17)
else()
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD 14)
endif()
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@ -16,22 +16,23 @@ set(CMAKE_CXX_EXTENSIONS OFF)
add_executable(${PROJECT_NAME} main.cc)
##########
# If you include the drogon source code locally in your project, use this method to add drogon
# add_subdirectory(drogon)
# ##############################################################################
# If you include the drogon source code locally in your project, use this method
# to add drogon
# add_subdirectory(drogon)
# target_link_libraries(${PROJECT_NAME} PRIVATE drogon)
##########
# ##############################################################################
find_package(Drogon CONFIG REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE Drogon::Drogon)
if(CMAKE_CXX_STANDARD LESS 17)
#With C++14, use boost to support any and string_view
message(STATUS "use c++14")
find_package(Boost 1.61.0 REQUIRED)
target_include_directories(${PROJECT_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
# With C++14, use boost to support any and string_view
message(STATUS "use c++14")
find_package(Boost 1.61.0 REQUIRED)
target_include_directories(${PROJECT_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
else()
message(STATUS "use c++17")
message(STATUS "use c++17")
endif()
aux_source_directory(controllers CTL_SRC)
@ -39,21 +40,22 @@ aux_source_directory(filters FILTER_SRC)
aux_source_directory(plugins PLUGIN_SRC)
aux_source_directory(models MODEL_SRC)
file(GLOB_RECURSE SCP_LIST ${CMAKE_CURRENT_SOURCE_DIR}/views/*.csp)
foreach(cspFile ${SCP_LIST})
message(STATUS "cspFile:" ${cspFile})
get_filename_component(classname ${cspFile} NAME_WE)
message(STATUS "view classname:" ${classname})
ADD_CUSTOM_COMMAND(OUTPUT ${classname}.h ${classname}.cc
COMMAND drogon_ctl
ARGS create view ${cspFile}
DEPENDS ${cspFile}
VERBATIM )
set(VIEWSRC ${VIEWSRC} ${classname}.cc)
endforeach()
drogon_create_views(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/views
${CMAKE_CURRENT_BINARY_DIR})
# use the following line to create views with namespaces.
# drogon_create_views(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/views
# ${CMAKE_CURRENT_BINARY_DIR} TRUE)
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/models)
target_sources(${PROJECT_NAME} PRIVATE ${SRC_DIR} ${CTL_SRC} ${FILTER_SRC} ${VIEWSRC} ${PLUGIN_SRC} ${MODEL_SRC})
################################
target_include_directories(${PROJECT_NAME}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/models)
target_sources(${PROJECT_NAME}
PRIVATE
${SRC_DIR}
${CTL_SRC}
${FILTER_SRC}
${PLUGIN_SRC}
${MODEL_SRC})
# ##############################################################################
# uncomment the following line for dynamically loading views
#set_property(TARGET ${PROJECT_NAME} PROPERTY ENABLE_EXPORTS ON)
# set_property(TARGET ${PROJECT_NAME} PROPERTY ENABLE_EXPORTS ON)

View File

@ -1,21 +1,5 @@
link_libraries(${PROJECT_NAME})
file(GLOB SCP_LIST ${CMAKE_CURRENT_SOURCE_DIR}/simple_example/*.csp)
foreach(cspFile ${SCP_LIST})
message(STATUS "cspFile:" ${cspFile})
get_filename_component(classname ${cspFile} NAME_WE)
message(STATUS "view classname:" ${classname})
add_custom_command(OUTPUT ${classname}.h ${classname}.cc
COMMAND drogon_ctl
ARGS
create
view
${cspFile}
DEPENDS ${cspFile}
VERBATIM)
set(VIEWSRC ${VIEWSRC} ${classname}.cc)
endforeach()
set(simple_example_sources
simple_example/CustomCtrl.cc
simple_example/CustomHeaderFilter.cc
@ -34,7 +18,8 @@ set(simple_example_sources
simple_example/DigestAuthFilter.cc
simple_example/main.cc)
add_executable(webapp ${simple_example_sources} ${VIEWSRC})
add_executable(webapp ${simple_example_sources})
drogon_create_views(webapp ${CMAKE_CURRENT_SOURCE_DIR}/simple_example ${CMAKE_CURRENT_BINARY_DIR})
add_dependencies(webapp drogon_ctl)
set(client_example_sources client_example/main.cc)

View File

@ -1,7 +1,7 @@
/**
*
* DrTemplateBase.h
* An Tao
* @file DrTemplateBase.h
* @author An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
@ -40,7 +40,7 @@ class DrTemplateBase : public virtual DrObjectBase
* drogon_ctl tool to create c++ source files.
*/
static std::shared_ptr<DrTemplateBase> newTemplate(
std::string templateName);
const std::string &templateName);
/// Generate the text string
/**

View File

@ -1,7 +1,7 @@
/**
*
* DrTemplateBase.cc
* An Tao
* @file DrTemplateBase.cc
* @author An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
@ -14,23 +14,50 @@
#include <drogon/DrClassMap.h>
#include <drogon/DrTemplateBase.h>
#include <memory>
#include <trantor/utils/Logger.h>
#include <memory>
#include <regex>
using namespace drogon;
std::shared_ptr<DrTemplateBase> DrTemplateBase::newTemplate(
std::string templateName)
const std::string &templateName)
{
LOG_TRACE << "http view name=" << templateName;
auto pos = templateName.find(".csp");
if (pos != std::string::npos)
auto l = templateName.length();
if (l >= 4 && templateName[l - 4] == '.' && templateName[l - 3] == 'c' &&
templateName[l - 2] == 's' && templateName[l - 1] == 'p')
{
if (pos == templateName.length() - 4)
std::string::size_type pos = 0;
std::string newName;
newName.reserve(templateName.size());
if (templateName[0] == '/' || templateName[0] == '\\')
{
templateName = templateName.substr(0, pos);
pos = 1;
}
else if (templateName[0] == '.' &&
(templateName[1] == '/' || templateName[1] == '\\'))
{
pos = 2;
}
while (pos < l - 4)
{
if (templateName[pos] == '/' || templateName[pos] == '\\')
{
newName.append("::");
}
else
{
newName.append(1, templateName[pos]);
}
++pos;
}
return std::shared_ptr<DrTemplateBase>(dynamic_cast<DrTemplateBase *>(
drogon::DrClassMap::newObject(newName)));
}
else
{
return std::shared_ptr<DrTemplateBase>(dynamic_cast<DrTemplateBase *>(
drogon::DrClassMap::newObject(templateName)));
}
return std::shared_ptr<DrTemplateBase>(dynamic_cast<DrTemplateBase*>(
drogon::DrClassMap::newObject(templateName)));
}

View File

@ -1,7 +1,7 @@
/**
*
* @file HttpResponseImpl.cc
* An Tao
* @author An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
@ -45,7 +45,7 @@ static inline void doResponseCreateAdvices(
}
}
}
static inline HttpResponsePtr genHttpResponse(std::string viewName,
static inline HttpResponsePtr genHttpResponse(const std::string &viewName,
const HttpViewData &data)
{
auto templ = DrTemplateBase::newTemplate(viewName);

View File

@ -118,6 +118,10 @@ if [ ! -f "Test_TestPlugin.h" -o ! -f "Test_TestPlugin.cc" ]; then
exit -1
fi
cd ../views
echo "Hello, world!" >> hello.csp
cd ../build
cmake .. $cmake_gen