readme-builder 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,199 @@
1
+ /**
2
+ * @file language_detector.cpp
3
+ * @brief Programming language detection system
4
+ * @details Implements a sophisticated system for detecting programming languages
5
+ * used in a project by analyzing file extensions and content patterns.
6
+ * Supports multiple detection strategies including extension matching
7
+ * and content-based analysis.
8
+ *
9
+ * @author Generated by README Builder
10
+ * @date 2025-02-17
11
+ *
12
+ * @note This implementation supports extensibility through custom language
13
+ * detection rules and pattern matching.
14
+ */
15
+
16
+
17
+ #include "../include/language_detector.hpp"
18
+ #include <iostream>
19
+ #include <fstream>
20
+ #include <vector>
21
+ #include <regex>
22
+
23
+
24
+ /**
25
+ * @brief Constructor initializing supported language mappings
26
+ * @details Sets up the initial mapping of file extensions to programming languages
27
+ */
28
+
29
+ LanguageDetector::LanguageDetector() {
30
+ // Initialize extension map
31
+ extensionMap = {
32
+ {".py", "Python"},
33
+ {".js", "JavaScript"},
34
+ {".ts", "TypeScript"},
35
+ {".cpp", "C++"},
36
+ {".hpp", "C++"},
37
+ {".h", "C/C++"},
38
+ {".c", "C"},
39
+ {".java", "Java"},
40
+ {".rs", "Rust"},
41
+ {".go", "Go"},
42
+ {".rb", "Ruby"},
43
+ {".php", "PHP"},
44
+ {".cs", "C#"},
45
+ {".swift", "Swift"},
46
+ {".kt", "Kotlin"},
47
+ {".r", "R"},
48
+ {".scala", "Scala"},
49
+ {".m", "Objective-C"},
50
+ {".sql", "SQL"},
51
+ {".sh", "Shell"}
52
+ };
53
+ }
54
+
55
+ /**
56
+ * @brief Analyzes file content to determine the programming language
57
+ * @details Examines file contents for language-specific patterns such as
58
+ * shebangs and syntax patterns when extension-based detection
59
+ * is insufficient
60
+ *
61
+ * @param filePath Path to the file being analyzed
62
+ * @return std::string Detected programming language or empty string if unknown
63
+ */
64
+
65
+ std::string LanguageDetector::analyzeFileContent(const std::string& filePath) {
66
+ std::ifstream file(filePath);
67
+ if (!file.is_open()) return "";
68
+
69
+ std::string line;
70
+ std::vector<std::string> firstLines;
71
+ int lineCount = 0;
72
+
73
+ // Read first 10 lines for analysis
74
+ while (std::getline(file, line) && lineCount < 10) {
75
+ firstLines.push_back(line);
76
+ lineCount++;
77
+ }
78
+
79
+ // Pattern matching for specific languages
80
+ for (const auto& line : firstLines) {
81
+ // Python shebang
82
+ if (std::regex_search(line, std::regex("^#!/usr/bin/env python"))) {
83
+ return "Python";
84
+ }
85
+ // Node.js shebang
86
+ if (std::regex_search(line, std::regex("^#!/usr/bin/env node"))) {
87
+ return "JavaScript";
88
+ }
89
+ // Ruby shebang
90
+ if (std::regex_search(line, std::regex("^#!/usr/bin/env ruby"))) {
91
+ return "Ruby";
92
+ }
93
+ }
94
+
95
+ return "";
96
+ }
97
+
98
+ /**
99
+ * @brief Analyzes all source files in a project
100
+ * @details Recursively traverses the project's src directory, analyzing each file
101
+ * to determine its programming language using both extension-based and
102
+ * content-based detection methods
103
+ *
104
+ * @param projectPath Root path of the project to analyze
105
+ */
106
+
107
+ void LanguageDetector::analyzeProject(const std::string& projectPath) {
108
+ try {
109
+ // Only analyze files in the src directory
110
+ std::filesystem::path srcPath = std::filesystem::path(projectPath) / "src";
111
+ if (!std::filesystem::exists(srcPath)) {
112
+ return;
113
+ }
114
+
115
+ for (const auto& entry : std::filesystem::directory_iterator(srcPath)) {
116
+ if (!entry.is_regular_file()) continue;
117
+ if (entry.path().filename().string()[0] == '.') continue;
118
+
119
+ std::string extension = entry.path().extension().string();
120
+ std::string detectedLanguage;
121
+
122
+ // First try extension-based detection
123
+ if (extensionMap.find(extension) != extensionMap.end()) {
124
+ detectedLanguage = extensionMap[extension];
125
+ } else {
126
+ // If extension not found, try content analysis
127
+ detectedLanguage = analyzeFileContent(entry.path().string());
128
+ }
129
+
130
+ if (!detectedLanguage.empty()) {
131
+ languageStats[detectedLanguage]++;
132
+ }
133
+ }
134
+ } catch (const std::filesystem::filesystem_error& e) {
135
+ std::cerr << "Error accessing directory: " << e.what() << std::endl;
136
+ }
137
+ }
138
+
139
+ /**
140
+ * @brief Retrieves the current language statistics
141
+ * @return std::unordered_map<std::string, int> Map of languages to file counts
142
+ */
143
+
144
+ std::unordered_map<std::string, int> LanguageDetector::getLanguageStatistics() const {
145
+ return languageStats;
146
+ }
147
+
148
+ /**
149
+ * @brief Resets all language statistics
150
+ * @details Clears all accumulated language statistics, preparing for a new analysis
151
+ */
152
+
153
+ void LanguageDetector::reset() {
154
+ languageStats.clear();
155
+ }
156
+
157
+ /**
158
+ * @brief Adds a custom file extension to language mapping
159
+ * @details Allows users to extend the language detection capabilities with
160
+ * custom file extensions
161
+ *
162
+ * @param extension File extension including the dot (e.g., ".custom")
163
+ * @param language Name of the programming language
164
+ */
165
+
166
+ void LanguageDetector::addCustomExtension(const std::string& extension, const std::string& language) {
167
+ extensionMap[extension] = language;
168
+ }
169
+
170
+ /**
171
+ * @brief Gets the total number of analyzed files
172
+ * @return int Total number of files analyzed
173
+ */
174
+
175
+ int LanguageDetector::getTotalFiles() const {
176
+ int total = 0;
177
+ for (const auto& stat : languageStats) {
178
+ total += stat.second;
179
+ }
180
+ return total;
181
+ }
182
+
183
+ /**
184
+ * @brief Determines the most frequently used programming language
185
+ * @return std::string Name of the primary programming language
186
+ */
187
+ std::string LanguageDetector::getPrimaryLanguage() const {
188
+ std::string primaryLang;
189
+ int maxCount = 0;
190
+
191
+ for (const auto& stat : languageStats) {
192
+ if (stat.second > maxCount) {
193
+ maxCount = stat.second;
194
+ primaryLang = stat.first;
195
+ }
196
+ }
197
+
198
+ return primaryLang;
199
+ }
@@ -0,0 +1,197 @@
1
+ /**
2
+ * @file license.cpp
3
+ * @brief License management and generation system
4
+ * @details Implements a comprehensive system for managing and generating software
5
+ * licenses. This system supports multiple common open source licenses
6
+ * including MIT, Apache 2.0, and GPL-3.0. Each license is stored with
7
+ * its full text, title, and a brief description explaining its key
8
+ * characteristics and use cases.
9
+ *
10
+ * @author Generated by README Builder
11
+ * @date 2025-02-17
12
+ *
13
+ * @note This implementation follows the official license texts from their
14
+ * respective sources and automatically handles the insertion of
15
+ * copyright year and holder information.
16
+ */
17
+
18
+ #include "license.hpp"
19
+ #include <ctime>
20
+ #include <stdexcept>
21
+
22
+ /**
23
+ * @brief Constructs a new License manager
24
+ * @details Initializes the license management system by:
25
+ * 1. Getting the current year for copyright notices
26
+ * 2. Setting up the license template database
27
+ *
28
+ * The constructor prepares all supported license templates with their
29
+ * official texts and descriptions for later use.
30
+ */
31
+
32
+ License::License() {
33
+ currentYear = getCurrentYear();
34
+ initializeLicenses();
35
+ }
36
+
37
+ /**
38
+ * @brief Initializes the database of supported licenses
39
+ * @details Sets up the internal storage of license templates, including:
40
+ * - Full license text with placeholders
41
+ * - License titles
42
+ * - Descriptions explaining license characteristics
43
+ *
44
+ * Currently supports:
45
+ * - MIT License
46
+ * - Apache License 2.0
47
+ * - GNU General Public License v3.0
48
+ *
49
+ * Each license is stored with placeholders for dynamic content
50
+ * (year and copyright holder) that get replaced during generation.
51
+ */
52
+
53
+ void License::initializeLicenses() {
54
+ licenses["MIT"] = {
55
+ "MIT License",
56
+ "MIT License\n\n"
57
+ "Copyright (c) [year] [fullname]\n\n"
58
+ "Permission is hereby granted, free of charge, to any person obtaining a copy "
59
+ "of this software and associated documentation files (the \"Software\"), to deal "
60
+ "in the Software without restriction, including without limitation the rights "
61
+ "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell "
62
+ "copies of the Software, and to permit persons to whom the Software is "
63
+ "furnished to do so, subject to the following conditions:\n\n"
64
+ "The above copyright notice and this permission notice shall be included in all "
65
+ "copies or substantial portions of the Software.\n\n"
66
+ "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR "
67
+ "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, "
68
+ "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE "
69
+ "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER "
70
+ "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, "
71
+ "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE "
72
+ "SOFTWARE.",
73
+ "A permissive license that lets people do anything with your code with proper attribution and without warranty."
74
+ };
75
+
76
+ licenses["Apache-2.0"] = {
77
+ "Apache License 2.0",
78
+ " Apache License\n"
79
+ " Version 2.0, January 2004\n"
80
+ " http://www.apache.org/licenses/\n\n"
81
+ "Copyright [year] [fullname]\n\n"
82
+ "Licensed under the Apache License, Version 2.0 (the \"License\");\n"
83
+ "you may not use this file except in compliance with the License.\n"
84
+ "You may obtain a copy of the License at\n\n"
85
+ " http://www.apache.org/licenses/LICENSE-2.0\n\n"
86
+ "Unless required by applicable law or agreed to in writing, software\n"
87
+ "distributed under the License is distributed on an \"AS IS\" BASIS,\n"
88
+ "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
89
+ "See the License for the specific language governing permissions and\n"
90
+ "limitations under the License.",
91
+ "A permissive license that also provides an express grant of patent rights from contributors to users."
92
+ };
93
+
94
+ licenses["GPL-3.0"] = {
95
+ "GNU General Public License v3.0",
96
+ "Copyright (C) [year] [fullname]\n\n"
97
+ "This program is free software: you can redistribute it and/or modify "
98
+ "it under the terms of the GNU General Public License as published by "
99
+ "the Free Software Foundation, either version 3 of the License, or "
100
+ "(at your option) any later version.\n\n"
101
+ "This program is distributed in the hope that it will be useful, "
102
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of "
103
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the "
104
+ "GNU General Public License for more details.\n\n"
105
+ "You should have received a copy of the GNU General Public License "
106
+ "along with this program. If not, see <https://www.gnu.org/licenses/>.",
107
+ "A copyleft license that requires anyone who distributes your code or a derivative work to make the source available under the same terms."
108
+ };
109
+ }
110
+
111
+ /**
112
+ * @brief Gets the current year for copyright notices
113
+ * @details Retrieves the current year from the system clock for use
114
+ * in license copyright statements. The year is formatted as
115
+ * a string to maintain consistency with license templates.
116
+ *
117
+ * @return std::string The current year as a string
118
+ */
119
+
120
+ std::string License::getCurrentYear() const {
121
+ time_t now = time(0);
122
+ tm* ltm = localtime(&now);
123
+ return std::to_string(1900 + ltm->tm_year);
124
+ }
125
+
126
+ /**
127
+ * @brief Lists all available license types
128
+ * @details Returns a vector of supported license identifiers (e.g., "MIT",
129
+ * "Apache-2.0", "GPL-3.0") that can be used with getLicenseContent().
130
+ *
131
+ * @return std::vector<std::string> List of available license identifiers
132
+ */
133
+
134
+ std::vector<std::string> License::getAvailableLicenses() const {
135
+ std::vector<std::string> available;
136
+ for (const auto& [key, value] : licenses) {
137
+ available.push_back(key);
138
+ }
139
+ return available;
140
+ }
141
+
142
+ /**
143
+ * @brief Generates a complete license text for a specific license type
144
+ * @details Creates a fully formatted license text by:
145
+ * 1. Retrieving the appropriate license template
146
+ * 2. Replacing [year] placeholder with current year
147
+ * 3. Replacing [fullname] placeholder with copyright holder
148
+ *
149
+ * @param licenseType The type of license to generate (e.g., "MIT")
150
+ * @param copyrightHolder The name of the copyright holder
151
+ * @return std::string Complete license text with all placeholders replaced
152
+ *
153
+ * @throws std::runtime_error If the requested license type is not supported
154
+ *
155
+ * @see getAvailableLicenses() For a list of supported license types
156
+ */
157
+
158
+ std::string License::getLicenseContent(const std::string& licenseType,
159
+ const std::string& copyrightHolder) const {
160
+ if (licenses.find(licenseType) == licenses.end()) {
161
+ throw std::runtime_error("Invalid license type");
162
+ }
163
+
164
+ std::string content = licenses.at(licenseType).content;
165
+
166
+ // Replace placeholders
167
+ size_t yearPos = content.find("[year]");
168
+ if (yearPos != std::string::npos) {
169
+ content.replace(yearPos, 6, currentYear);
170
+ }
171
+
172
+ size_t namePos = content.find("[fullname]");
173
+ if (namePos != std::string::npos) {
174
+ content.replace(namePos, 10, copyrightHolder);
175
+ }
176
+
177
+ return content;
178
+ }
179
+
180
+ /**
181
+ * @brief Retrieves the description of a specific license
182
+ * @details Returns a human-readable description of the license's key
183
+ * characteristics, including its permissions, conditions, and
184
+ * limitations.
185
+ *
186
+ * @param licenseType The type of license to describe (e.g., "MIT")
187
+ * @return std::string Description of the license
188
+ *
189
+ * @throws std::runtime_error If the requested license type is not supported
190
+ */
191
+
192
+ std::string License::getLicenseDescription(const std::string& licenseType) const {
193
+ if (licenses.find(licenseType) == licenses.end()) {
194
+ throw std::runtime_error("Invalid license type");
195
+ }
196
+ return licenses.at(licenseType).description;
197
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @file main.cpp
3
+ * @brief Main entry point for the README generation system
4
+ * @details This file contains the main function that orchestrates the README
5
+ * generation process, including project analysis and user input collection.
6
+ *
7
+ * @author Generated by README Builder
8
+ * @date 2025-02-17
9
+ */
10
+
11
+ #include "../include/readme_builder.hpp"
12
+ #include <iostream>
13
+
14
+ /**
15
+ * @brief Program entry point
16
+ * @details Initializes the README generator, collects user input, and generates
17
+ * a comprehensive README.md file with project statistics and structure.
18
+ *
19
+ * @return int Exit code (0 for success, 1 for error)
20
+ *
21
+ * @throws std::exception Various exceptions from the README generation process
22
+ */
23
+
24
+ int main() {
25
+ try {
26
+ ReadmeBuilder generator;
27
+
28
+ // First get user input for project name and description
29
+ generator.run();
30
+
31
+ // Then analyze the project for language statistics
32
+ generator.generateWithLanguageDetection();
33
+
34
+ std::cout << "README.md has been generated successfully with project structure and language statistics!" << std::endl;
35
+ } catch (const std::exception& e) {
36
+ std::cerr << "Error: " << e.what() << std::endl;
37
+ return 1;
38
+ }
39
+ return 0;
40
+ }
@@ -0,0 +1,226 @@
1
+ /**
2
+ * @file readme_builder.cpp
3
+ * @brief README generation system
4
+ * @details Implements a comprehensive README generator that analyzes project structure,
5
+ * detects programming languages used, and creates well-structured documentation.
6
+ * The system automatically detects project characteristics and generates
7
+ * appropriate installation instructions based on the build system used.
8
+ *
9
+ * @author Generated by README Builder
10
+ * @date 2025-02-17
11
+ *
12
+ * @note This implementation focuses on generating standardized, informative README
13
+ * files that follow best practices in project documentation.
14
+ */
15
+
16
+
17
+ #include "../include/readme_builder.hpp"
18
+ #include "../include/language_detector.hpp"
19
+ #include "../include/build_detector.hpp"
20
+ #include <iostream>
21
+ #include <fstream>
22
+ #include <sstream>
23
+ #include <iomanip>
24
+ #include <ctime>
25
+
26
+ /**
27
+ * @brief Locates the root directory of the project
28
+ * @details Searches upward from the given path until it finds common project markers
29
+ * such as .git directory, src directory, or CMakeLists.txt
30
+ *
31
+ * @param startPath The path to start searching from
32
+ * @return std::string The absolute path to the project root
33
+ */
34
+
35
+ std::string ReadmeBuilder::findProjectRoot(const std::string& startPath) const {
36
+ std::filesystem::path current(startPath);
37
+
38
+ while (current.has_parent_path()) {
39
+ bool hasGit = std::filesystem::exists(current / ".git");
40
+ bool hasSrc = std::filesystem::exists(current / "src");
41
+ bool hasCMake = std::filesystem::exists(current / "CMakeLists.txt");
42
+
43
+ if (hasGit || hasSrc || hasCMake) {
44
+ return current.string();
45
+ }
46
+
47
+ current = current.parent_path();
48
+ }
49
+
50
+ return startPath;
51
+ }
52
+
53
+ /**
54
+ * @brief Gets the current date in YYYY-MM-DD format
55
+ * @return std::string Formatted current date
56
+ */
57
+
58
+ std::string ReadmeBuilder::getCurrentDate() const {
59
+ time_t now = time(0);
60
+ tm* ltm = localtime(&now);
61
+ std::string date = std::to_string(1900 + ltm->tm_year) + "-" +
62
+ std::to_string(1 + ltm->tm_mon) + "-" +
63
+ std::to_string(ltm->tm_mday);
64
+ return date;
65
+ }
66
+
67
+ /**
68
+ * @brief Generates the language statistics section of the README
69
+ * @details Creates a formatted section showing the percentage and count of files
70
+ * for each programming language detected in the project
71
+ *
72
+ * @return std::string Markdown-formatted language statistics
73
+ */
74
+
75
+ std::string ReadmeBuilder::generateLanguageSection() const {
76
+ std::stringstream ss;
77
+ ss << "## Languages Used\n\n";
78
+
79
+ for (const auto& [language, count] : languageStats) {
80
+ double percentage = (static_cast<double>(count) / totalFiles) * 100;
81
+ ss << "- " << language << ": " << count << " files ("
82
+ << std::fixed << std::setprecision(1) << percentage << "%)\n";
83
+ }
84
+
85
+ return ss.str();
86
+ }
87
+
88
+ /**
89
+ * @brief Generates a tree-like structure of project source files
90
+ * @details Recursively traverses the project directory and creates a formatted
91
+ * listing of source files, focusing on the src directory
92
+ *
93
+ * @param path The directory path to analyze
94
+ * @param depth Current recursion depth
95
+ * @return std::string Markdown-formatted project structure
96
+ */
97
+
98
+ std::string ReadmeBuilder::generateProjectStructure(const std::string& path, int depth) const {
99
+ std::stringstream ss;
100
+
101
+ if (depth == 0) {
102
+ ss << "\n## Source Files\n\n";
103
+ }
104
+
105
+ // Only process src directory
106
+ std::filesystem::path srcPath = std::filesystem::path(path) / "src";
107
+ if (!std::filesystem::exists(srcPath)) {
108
+ return ss.str();
109
+ }
110
+
111
+ for (const auto& entry : std::filesystem::directory_iterator(srcPath)) {
112
+ if (!entry.is_regular_file()) continue;
113
+ if (entry.path().filename().string()[0] == '.') continue;
114
+
115
+ ss << "- " << entry.path().filename().string() << "\n";
116
+ }
117
+
118
+ return ss.str();
119
+ }
120
+
121
+ /**
122
+ * @brief Generates the README.md file
123
+ * @details Combines all gathered information and user input to create a comprehensive
124
+ * README.md file in the project root directory
125
+ *
126
+ * @throws std::runtime_error If unable to create or write to README.md
127
+ */
128
+
129
+ void ReadmeBuilder::generateFile() {
130
+ std::filesystem::path readmePath = std::filesystem::path(projectRoot) / "README.md";
131
+ std::ofstream readme(readmePath);
132
+ if (!readme.is_open()) {
133
+ throw std::runtime_error("Could not create README.md file in project root");
134
+ }
135
+
136
+ readme << "# " << projectName << "\n\n"
137
+ << description << "\n\n"
138
+ << "Last updated: " << getCurrentDate() << "\n\n";
139
+
140
+ if (totalFiles > 0) {
141
+ readme << "## Project Overview\n\n"
142
+ << "This project is primarily written in " << primaryLanguage
143
+ << " and contains " << totalFiles << " source files.\n\n"
144
+ << generateLanguageSection()
145
+ << generateProjectStructure(projectRoot);
146
+ }
147
+
148
+ // Use the build system detector to generate installation instructions
149
+ BuildSystemDetector detector(projectRoot);
150
+ readme << detector.generateInstallationInstructions();
151
+
152
+ readme << "## Usage\n\n"
153
+ << "Add instructions on how to use your project.\n\n"
154
+ << "## Contributing\n\n"
155
+ << "Instructions for how to contribute to the project.\n\n"
156
+ << "## License\n\n"
157
+ << "Specify your project license here.\n";
158
+
159
+ readme.close();
160
+ std::cout << "README.md has been generated successfully in project root!" << std::endl;
161
+ }
162
+
163
+ /**
164
+ * @brief Constructor for ReadmeBuilder with pre-analyzed statistics
165
+ * @details Initializes the README builder with pre-computed language statistics
166
+ *
167
+ * @param name Project name
168
+ * @param stats Map of language statistics
169
+ * @param primary Primary programming language used
170
+ * @param total Total number of source files
171
+ */
172
+
173
+ ReadmeBuilder::ReadmeBuilder(const std::string& name,
174
+ const std::unordered_map<std::string, int>& stats,
175
+ const std::string& primary,
176
+ int total)
177
+ : projectName(name), languageStats(stats), primaryLanguage(primary), totalFiles(total) {
178
+ projectRoot = findProjectRoot(std::filesystem::current_path().string());
179
+ }
180
+
181
+ /**
182
+ * @brief Interactively collects project information from user
183
+ * @details Prompts the user for project title and description
184
+ *
185
+ * @throws std::runtime_error If required information is not provided
186
+ */
187
+
188
+ void ReadmeBuilder::run() {
189
+ std::cout << "Enter project title: ";
190
+ std::getline(std::cin, projectName);
191
+
192
+ if (projectName.empty()) {
193
+ throw std::runtime_error("Project title cannot be empty");
194
+ }
195
+
196
+ std::cout << "Enter project description: ";
197
+ std::getline(std::cin, description);
198
+
199
+ if (description.empty()) {
200
+ throw std::runtime_error("Project description cannot be empty");
201
+ }
202
+
203
+ generateFile();
204
+ }
205
+
206
+ /**
207
+ * @brief Analyzes project and generates README with language statistics
208
+ * @details Uses LanguageDetector to analyze the project structure and
209
+ * automatically generate language statistics
210
+ */
211
+
212
+ void ReadmeBuilder::generateWithLanguageDetection() {
213
+ LanguageDetector detector;
214
+ detector.analyzeProject(projectRoot);
215
+
216
+ languageStats = detector.getLanguageStatistics();
217
+ primaryLanguage = detector.getPrimaryLanguage();
218
+ totalFiles = detector.getTotalFiles();
219
+
220
+ if (projectName.empty()) {
221
+ projectName = std::filesystem::path(projectRoot).filename().string();
222
+ }
223
+
224
+ generateFile();
225
+ }
226
+
@@ -0,0 +1,4 @@
1
+ # lib/readme_builder/version.rb
2
+ module ReadmeBuilder
3
+ VERSION = "0.1.0"
4
+ end
@@ -0,0 +1,31 @@
1
+ # lib/readme_builder.rb
2
+
3
+ ##
4
+ # The ReadmeBuilder module provides functionality to automatically generate
5
+ # README and LICENSE files for software projects through a command-line interface.
6
+ #
7
+ # @example Using from command line
8
+ # $ readme_builder
9
+ # Enter project name: My Project
10
+ # Enter description: A great tool
11
+ # Select license: MIT
12
+ #
13
+ # @author Your Name
14
+ # @since 0.1.0
15
+ module ReadmeBuilder
16
+ ##
17
+ # Custom error class for ReadmeBuilder-specific exceptions.
18
+ # Used to distinguish errors from this gem from standard Ruby errors.
19
+ #
20
+ # @example Handling specific errors
21
+ # begin
22
+ # # Some readme_builder operation
23
+ # rescue ReadmeBuilder::Error => e
24
+ # puts "ReadmeBuilder error: #{e.message}"
25
+ # end
26
+ class Error < StandardError; end
27
+ end
28
+
29
+ # Load version and native extension
30
+ require 'readme_builder/version'
31
+ require 'readme_builder/native' # Load the compiled C++ extension