1919namespace cmkr {
2020namespace gen {
2121
22- inline std::string to_upper (const std::string &str) {
22+ static std::string to_upper (const std::string &str) {
2323 std::string temp;
2424 temp.reserve (str.size ());
2525 for (auto c : str) {
@@ -28,16 +28,16 @@ inline std::string to_upper(const std::string &str) {
2828 return temp;
2929}
3030
31- template < typename ... Args>
32- std::string format ( const char *fmt, Args... args) {
33- auto sz = snprintf ( nullptr , 0 , fmt, args...) + 1 ;
34- char *buf = new char [sz] ;
35- int ret = snprintf (buf, sz, fmt, args...);
36- if (ret != sz - 1 )
37- throw std::runtime_error ( " Error formatting string! " );
38- std::string temp (buf, buf + sz - 1 );
39- delete[] buf;
40- return temp ;
31+ static std::string format ( const char *format, tsl::ordered_map<std::string, std::string> variables) {
32+ std::string s = format;
33+ for ( const auto &itr : variables) {
34+ size_t start_pos = 0 ;
35+ while ((start_pos = s. find (itr. first , start_pos)) != std::string::npos) {
36+ s. replace (start_pos, itr. first . length (), itr. second );
37+ start_pos += itr. second . length ( );
38+ }
39+ }
40+ return s ;
4141}
4242
4343static std::vector<std::string> expand_cmake_path (const fs::path &name, const fs::path &toml_dir) {
@@ -89,52 +89,47 @@ static std::vector<std::string> expand_cmake_paths(const std::vector<std::string
8989 return result;
9090}
9191
92- int generate_project (const char *str) {
93- fs::create_directory (" src" );
94- fs::create_directory (" include" );
95- const auto dir_name = fs::current_path ().stem ().string ();
96- std::string mainbuf;
97- std::string installed;
98- std::string target;
99- std::string dest;
100- if (!strcmp (str, " executable" )) {
101- mainbuf = format (hello_world, " main" );
102- installed = " targets" ;
103- target = dir_name;
104- dest = " bin" ;
105- } else if (!strcmp (str, " static" ) || !strcmp (str, " shared" ) || !strcmp (str, " library" )) {
106- mainbuf = format (hello_world, " test" );
107- installed = " targets" ;
108- target = dir_name;
109- dest = " lib" ;
110- } else if (!strcmp (str, " interface" )) {
111- installed = " files" ;
112- target = " include/*.h" ;
113- dest = " include/" + dir_name;
114- } else {
115- throw std::runtime_error (" Unknown project type " + std::string (str) +
116- " ! Supported types are: executable, library, shared, static, interface" );
92+ static void create_file (const fs::path &path, const std::string &contents) {
93+ if (!path.parent_path ().empty ()) {
94+ fs::create_directories (path.parent_path ());
11795 }
118-
119- const auto tomlbuf = format (cmake_toml, dir_name.c_str (), dir_name.c_str (), str, installed.c_str (), target.c_str (), dest.c_str ());
120-
121- if (strcmp (str, " interface" )) {
122- std::ofstream ofs (" src/main.cpp" , std::ios::binary);
123- if (ofs.is_open ()) {
124- ofs << mainbuf;
125- }
126- ofs.flush ();
127- ofs.close ();
96+ std::ofstream ofs (path, std::ios::binary);
97+ if (!ofs) {
98+ throw std::runtime_error (" Failed to create " + path.string ());
12899 }
100+ ofs << contents;
101+ }
129102
130- std::ofstream ofs2 (" cmake.toml" , std::ios::binary);
131- if (ofs2.is_open ()) {
132- ofs2 << tomlbuf;
103+ void generate_project (const std::string &type) {
104+ const auto name = fs::current_path ().stem ().string ();
105+ if (fs::exists (fs::current_path () / " cmake.toml" )) {
106+ throw std::runtime_error (" Cannot initialize a project when cmake.toml already exists!" );
133107 }
134- ofs2.flush ();
135- ofs2.close ();
136108
137- return 0 ;
109+ tsl::ordered_map<std::string, std::string> variables = {
110+ {" @name" , name},
111+ {" @type" , type},
112+ };
113+
114+ if (!fs::is_empty (fs::current_path ())) {
115+ create_file (" cmake.toml" , format (toml_migration, variables));
116+ puts (" Generated migration cmake.toml in existing project directory..." );
117+ return ;
118+ }
119+
120+ if (type == " executable" ) {
121+ create_file (" cmake.toml" , format (toml_executable, variables));
122+ create_file (" src/" + name + " /main.cpp" , format (cpp_executable, variables));
123+ } else if (type == " static" || type == " shared" || type == " library" ) {
124+ create_file (" cmake.toml" , format (toml_library, variables));
125+ create_file (" src/" + name + " /" + name + " .cpp" , format (cpp_library, variables));
126+ create_file (" include/" + name + " /" + name + " .hpp" , format (hpp_library, variables));
127+ } else if (type == " interface" ) {
128+ create_file (" cmake.toml" , format (toml_interface, variables));
129+ create_file (" include/" + name + " /" + name + " .hpp" , format (hpp_interface, variables));
130+ } else {
131+ throw std::runtime_error (" Unknown project type " + type + " ! Supported types are: executable, library, shared, static, interface" );
132+ }
138133}
139134
140135struct CommandEndl {
@@ -440,7 +435,7 @@ static std::string vcpkg_escape_identifier(const std::string &name) {
440435 return escaped;
441436}
442437
443- int generate_cmake (const char *path, const parser::Project *parent_project) {
438+ void generate_cmake (const char *path, const parser::Project *parent_project) {
444439 if (!fs::exists (fs::path (path) / " cmake.toml" )) {
445440 throw std::runtime_error (" No cmake.toml found!" );
446441 }
@@ -494,14 +489,7 @@ int generate_cmake(const char *path, const parser::Project *parent_project) {
494489
495490 fs::path cmkr_include (project.cmkr_include );
496491 if (!project.cmkr_include .empty () && !fs::exists (cmkr_include) && cmkr_include.is_relative ()) {
497- if (!cmkr_include.parent_path ().empty ()) {
498- fs::create_directories (cmkr_include.parent_path ());
499- }
500- std::ofstream ofs (cmkr_include.string (), std::ios::binary);
501- if (!ofs) {
502- throw std::runtime_error (" Failed to create " + project.cmkr_include );
503- }
504- ofs.write (resources::cmkr, strlen (resources::cmkr));
492+ create_file (cmkr_include, resources::cmkr);
505493 }
506494 }
507495
@@ -910,12 +898,7 @@ int generate_cmake(const char *path, const parser::Project *parent_project) {
910898 }();
911899
912900 if (should_regenerate) {
913- std::ofstream ofs (list_path, std::ios::binary);
914- if (ofs.is_open ()) {
915- ofs << ss.str ();
916- } else {
917- throw std::runtime_error (" Failed to write " + list_path.string ());
918- }
901+ create_file (list_path, ss.str ());
919902 }
920903
921904 auto generate_subdir = [path, &project](const fs::path &sub) {
@@ -941,28 +924,6 @@ int generate_cmake(const char *path, const parser::Project *parent_project) {
941924 for (const auto &subdir : project.subdirs ) {
942925 generate_subdir (subdir.name );
943926 }
944-
945- return 0 ;
946927}
947928} // namespace gen
948929} // namespace cmkr
949-
950- int cmkr_gen_generate_project (const char *typ) {
951- try {
952- return cmkr::gen::generate_project (typ);
953- } catch (const std::system_error &e) {
954- return e.code ().value ();
955- } catch (...) {
956- return cmkr::error::Status (cmkr::error::Status::Code::InitError);
957- }
958- }
959-
960- int cmkr_gen_generate_cmake (const char *path) {
961- try {
962- return cmkr::gen::generate_cmake (path);
963- } catch (const std::system_error &e) {
964- return e.code ().value ();
965- } catch (...) {
966- return cmkr::error::Status (cmkr::error::Status::Code::GenerationError);
967- }
968- }
0 commit comments