ratatui_ruby-devtools 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/AGENTS.md +1 -1
- data/CHANGELOG.md +63 -6
- data/README.md +49 -21
- data/Rakefile +1 -1
- data/bin/setup +20 -6
- data/bin/setup.ps1 +74 -0
- data/doc/contributors/documentation_style.md +3 -4
- data/exe/scaffold +8 -342
- data/lib/ratatui_ruby/devtools/scaffold/scaffold_config.rb +67 -0
- data/lib/ratatui_ruby/devtools/scaffold/template_renderer.rb +282 -0
- data/lib/ratatui_ruby/devtools/site_tasks/build.rake +10 -15
- data/lib/ratatui_ruby/devtools/task_scope.rb +24 -0
- data/lib/ratatui_ruby/devtools/tasks/autodoc_tasks.rb +31 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/bump_workflow.rb +71 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/changelog.rb +60 -3
- data/lib/ratatui_ruby/devtools/tasks/bump/github_project.rb +26 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/history.rb +3 -3
- data/lib/ratatui_ruby/devtools/tasks/bump/links.rb +39 -24
- data/lib/ratatui_ruby/devtools/tasks/bump/manifest.rb +9 -17
- data/lib/ratatui_ruby/devtools/tasks/bump/no_crate.rb +19 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/no_links.rb +22 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/patch_release.rb +25 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/release_branch.rb +17 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/release_from_trunk.rb +48 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/repository.rb +143 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/ruby_gem.rb +65 -59
- data/lib/ratatui_ruby/devtools/tasks/bump/rust_crate.rb +42 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/sem_ver.rb +127 -10
- data/lib/ratatui_ruby/devtools/tasks/bump/source_hut_project.rb +26 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/unbranched_release.rb +20 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/unreleased_section.rb +19 -1
- data/lib/ratatui_ruby/devtools/tasks/bump_tasks.rb +47 -0
- data/lib/ratatui_ruby/devtools/tasks/cargo_tasks.rb +57 -0
- data/lib/ratatui_ruby/devtools/tasks/doc/documentation.rb +59 -0
- data/lib/ratatui_ruby/devtools/tasks/doc/link/file_url.rb +30 -0
- data/lib/ratatui_ruby/devtools/tasks/doc/link/relative_path.rb +61 -0
- data/lib/ratatui_ruby/devtools/tasks/doc/link/web_url.rb +55 -0
- data/lib/ratatui_ruby/devtools/tasks/doc/link.rb +52 -0
- data/lib/ratatui_ruby/devtools/tasks/doc/link_audit.rb +116 -0
- data/lib/ratatui_ruby/devtools/tasks/doc/problem.rb +40 -0
- data/lib/ratatui_ruby/devtools/tasks/doc/source_file.rb +93 -0
- data/lib/ratatui_ruby/devtools/tasks/doc_tasks.rb +937 -0
- data/lib/ratatui_ruby/devtools/tasks/license/blame.rb +72 -0
- data/lib/ratatui_ruby/devtools/tasks/license/changed_files.rb +34 -0
- data/lib/ratatui_ruby/devtools/tasks/license/contribution.rb +12 -0
- data/lib/ratatui_ruby/devtools/tasks/license/copyright.rb +47 -0
- data/lib/ratatui_ruby/devtools/tasks/license/directory_licensing.rb +42 -0
- data/lib/ratatui_ruby/devtools/tasks/license/existing_header.rb +21 -0
- data/lib/ratatui_ruby/devtools/tasks/license/header_revision.rb +45 -0
- data/lib/ratatui_ruby/devtools/tasks/license/licensed_file.rb +39 -0
- data/lib/ratatui_ruby/devtools/tasks/license/licensing.rb +35 -0
- data/lib/ratatui_ruby/devtools/tasks/license/markdown_document.rb +23 -0
- data/lib/ratatui_ruby/devtools/tasks/license/markdown_files.rb +31 -0
- data/lib/ratatui_ruby/devtools/tasks/license/markdown_header_syntax.rb +104 -0
- data/lib/ratatui_ruby/devtools/tasks/license/markdown_snippet_syntax.rb +159 -0
- data/lib/ratatui_ruby/devtools/tasks/license/missing_header.rb +18 -0
- data/lib/ratatui_ruby/devtools/tasks/license/rbs_files.rb +27 -0
- data/lib/ratatui_ruby/devtools/tasks/license/rbs_header_syntax.rb +31 -0
- data/lib/ratatui_ruby/devtools/tasks/license/rdoc_comment.rb +51 -0
- data/lib/ratatui_ruby/devtools/tasks/license/rdoc_examples.rb +41 -0
- data/lib/ratatui_ruby/devtools/tasks/license/rdoc_snippet_syntax.rb +119 -0
- data/lib/ratatui_ruby/devtools/tasks/license/renewal.rb +17 -0
- data/lib/ratatui_ruby/devtools/tasks/license/reuse_annotated_file.rb +12 -0
- data/lib/ratatui_ruby/devtools/tasks/license/reuse_tool.rb +34 -0
- data/lib/ratatui_ruby/devtools/tasks/license/ruby_comment_header.rb +49 -0
- data/lib/ratatui_ruby/devtools/tasks/license/ruby_files.rb +36 -0
- data/lib/ratatui_ruby/devtools/tasks/license/ruby_header_syntax.rb +39 -0
- data/lib/ratatui_ruby/devtools/tasks/license/rust_files.rb +27 -0
- data/lib/ratatui_ruby/devtools/tasks/license/rust_header_syntax.rb +59 -0
- data/lib/ratatui_ruby/devtools/tasks/license/snippet.rb +44 -0
- data/lib/ratatui_ruby/devtools/tasks/license/snippet_file.rb +29 -0
- data/lib/ratatui_ruby/devtools/tasks/license/snippet_opening.rb +39 -0
- data/lib/ratatui_ruby/devtools/tasks/license/snippet_revision.rb +75 -0
- data/lib/ratatui_ruby/devtools/tasks/license/spdx_header.rb +42 -0
- data/lib/ratatui_ruby/devtools/tasks/license/unknown_file.rb +12 -0
- data/lib/ratatui_ruby/devtools/tasks/license/unlicensed_files.rb +69 -0
- data/lib/ratatui_ruby/devtools/tasks/license/wrapped_snippet.rb +30 -0
- data/lib/ratatui_ruby/devtools/tasks/license_tasks.rb +71 -0
- data/lib/ratatui_ruby/devtools/tasks/lint/gem_lockfile.rb +29 -0
- data/lib/ratatui_ruby/devtools/tasks/lint/supported_rubies.rb +18 -0
- data/lib/ratatui_ruby/devtools/tasks/lint_tasks.rb +100 -0
- data/lib/ratatui_ruby/devtools/tasks/release/platform_gem.rb +21 -12
- data/lib/ratatui_ruby/devtools/tasks/release/versioned_binary.rb +1 -1
- data/lib/ratatui_ruby/devtools/tasks/release_tasks.rb +80 -0
- data/lib/ratatui_ruby/devtools/tasks/reuse_tasks.rb +39 -0
- data/lib/ratatui_ruby/devtools/tasks/{test.rake → test_tasks.rb} +13 -4
- data/lib/ratatui_ruby/devtools/tasks/website/hosted_source_tree.rb +24 -0
- data/lib/ratatui_ruby/devtools/tasks/website/index_page.rb +1 -4
- data/lib/ratatui_ruby/devtools/tasks/website/source_tree.rb +63 -0
- data/lib/ratatui_ruby/devtools/tasks/website/versioned_documentation.rb +14 -13
- data/lib/ratatui_ruby/devtools/tasks/website_tasks.rb +49 -0
- data/lib/ratatui_ruby/devtools/templates/.github/workflows/build-gems.yml.erb +7 -1
- data/lib/ratatui_ruby/devtools/templates/.github/workflows/ci.yml.erb +2 -2
- data/lib/ratatui_ruby/devtools/templates/.gitignore.erb +2 -1
- data/lib/ratatui_ruby/devtools/templates/.rubocop.yml.erb +1 -1
- data/lib/ratatui_ruby/devtools/templates/AGENTS.md.erb +1 -1
- data/lib/ratatui_ruby/devtools/templates/CHANGELOG.md.erb +3 -1
- data/lib/ratatui_ruby/devtools/templates/CONTRIBUTING.md.erb +3 -3
- data/lib/ratatui_ruby/devtools/templates/Gemfile.erb +2 -3
- data/lib/ratatui_ruby/devtools/templates/README.md.erb +7 -7
- data/lib/ratatui_ruby/devtools/templates/REUSE.toml.erb +1 -1
- data/lib/ratatui_ruby/devtools/templates/bin/setup.erb +5 -1
- data/lib/ratatui_ruby/devtools/templates/bin/setup.ps1.erb +5 -1
- data/lib/ratatui_ruby/devtools/templates/doc/concepts/application_architecture.md.erb +2 -2
- data/lib/ratatui_ruby/devtools/templates/doc/concepts/application_testing.md.erb +3 -3
- data/lib/ratatui_ruby/devtools/templates/doc/getting_started/quickstart.md.erb +4 -4
- data/lib/ratatui_ruby/devtools/templates/ext/Cargo.toml.erb +1 -1
- data/lib/ratatui_ruby/devtools/templates/gemspec.erb +1 -1
- data/lib/ratatui_ruby/devtools/templates/mise.toml.erb +3 -3
- data/lib/ratatui_ruby/devtools/version.rb +1 -1
- data/lib/ratatui_ruby/devtools.rb +54 -71
- data/mise.toml +2 -2
- data/sig/ratatui_ruby/devtools.rbs +16 -1
- metadata +93 -34
- data/.builds/ruby-4.0.yml +0 -38
- data/lib/ratatui_ruby/devtools/tasks/autodoc.rake +0 -21
- data/lib/ratatui_ruby/devtools/tasks/bump.rake +0 -80
- data/lib/ratatui_ruby/devtools/tasks/cargo.rake +0 -47
- data/lib/ratatui_ruby/devtools/tasks/doc.rake +0 -887
- data/lib/ratatui_ruby/devtools/tasks/license/headers_md.rb +0 -276
- data/lib/ratatui_ruby/devtools/tasks/license/headers_rb.rb +0 -236
- data/lib/ratatui_ruby/devtools/tasks/license/license_utils.rb +0 -143
- data/lib/ratatui_ruby/devtools/tasks/license/snippets_md.rb +0 -353
- data/lib/ratatui_ruby/devtools/tasks/license/snippets_rdoc.rb +0 -186
- data/lib/ratatui_ruby/devtools/tasks/license.rake +0 -91
- data/lib/ratatui_ruby/devtools/tasks/lint.rake +0 -80
- data/lib/ratatui_ruby/devtools/tasks/release.rake +0 -87
- data/lib/ratatui_ruby/devtools/tasks/resources/rubies.yml +0 -7
- data/lib/ratatui_ruby/devtools/tasks/reuse.rake +0 -104
- data/lib/ratatui_ruby/devtools/tasks/website.rake +0 -37
- data/lib/ratatui_ruby/devtools/templates/.builds/ruby.yml.erb +0 -47
- data/lib/ratatui_ruby/devtools/templates/tasks/resources/index.html.erb +0 -45
- data/lib/ratatui_ruby/devtools/templates/tasks/resources/rubies.yml.erb +0 -8
data/exe/scaffold
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
#
|
|
29
29
|
# --author NAME Copyright holder name (default: from git config)
|
|
30
30
|
# --email EMAIL Copyright holder email (default: from git config)
|
|
31
|
-
# --license ID SPDX license identifier (default:
|
|
31
|
+
# --license ID SPDX license identifier (default: LGPL-3.0-or-later)
|
|
32
32
|
# --dir PATH Parent directory for new gem (default: current directory)
|
|
33
33
|
# --update Update existing project (diff + prompt for conflicts)
|
|
34
34
|
# --force Remove existing directory if present
|
|
@@ -42,347 +42,11 @@
|
|
|
42
42
|
# scaffold ratatui_ruby-framework --dir ~/Developer
|
|
43
43
|
# scaffold rooibos --update --dir ~/Developer
|
|
44
44
|
|
|
45
|
-
require "erb"
|
|
46
45
|
require "fileutils"
|
|
47
46
|
require "optparse"
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
# Holds all parameters needed to render templates. Auto-discovers author info
|
|
52
|
-
# from git config if not provided.
|
|
53
|
-
class ScaffoldConfig
|
|
54
|
-
# The gem name to scaffold.
|
|
55
|
-
attr_accessor :gem_name
|
|
56
|
-
|
|
57
|
-
# The copyright holder's name.
|
|
58
|
-
attr_accessor :author
|
|
59
|
-
|
|
60
|
-
# The copyright holder's email.
|
|
61
|
-
attr_accessor :email
|
|
62
|
-
|
|
63
|
-
# The SPDX license identifier.
|
|
64
|
-
attr_accessor :license
|
|
65
|
-
|
|
66
|
-
# The output directory path.
|
|
67
|
-
attr_accessor :output_dir
|
|
68
|
-
|
|
69
|
-
# Whether this gem includes a Rust native extension.
|
|
70
|
-
attr_accessor :has_rust
|
|
71
|
-
|
|
72
|
-
# Creates a new config with defaults from git.
|
|
73
|
-
#
|
|
74
|
-
# Reads author name and email from git config. Sets default license to
|
|
75
|
-
# LGPL-3.0-or-later. Override any accessor after creation.
|
|
76
|
-
def initialize
|
|
77
|
-
@license = "LGPL-3.0-or-later"
|
|
78
|
-
@author = `git config user.name`.strip
|
|
79
|
-
@email = `git config user.email`.strip
|
|
80
|
-
@has_rust = false
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
# The gem name with underscores (for module names).
|
|
84
|
-
def module_name
|
|
85
|
-
gem_name.split("-").map { |s| s.split("_").map(&:capitalize).join }.join("::")
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
# The gem name with slashes (for require paths).
|
|
89
|
-
def require_path
|
|
90
|
-
gem_name.tr("-", "/")
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Copyright holder string for SPDX headers.
|
|
94
|
-
def copyright_holder
|
|
95
|
-
"#{author} <#{email}>"
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
# Current year for copyright.
|
|
99
|
-
def year
|
|
100
|
-
Time.now.year
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
# Ruby versions to test in CI.
|
|
104
|
-
def ruby_versions
|
|
105
|
-
%w[3.2 3.3 3.4 4.0.1]
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# Renders ERB templates into the target directory.
|
|
110
|
-
#
|
|
111
|
-
# Templates use ERB to inject gem-specific values. This class handles the
|
|
112
|
-
# rendering and file creation with proper directory structure.
|
|
113
|
-
class TemplateRenderer
|
|
114
|
-
# Creates a new renderer with config and paths.
|
|
115
|
-
#
|
|
116
|
-
# [config] The ScaffoldConfig with gem parameters.
|
|
117
|
-
# [templates_dir] Path to the ERB templates.
|
|
118
|
-
# [output_dir] Path where rendered files are written.
|
|
119
|
-
def initialize(config, templates_dir, output_dir, update_mode: false)
|
|
120
|
-
@config = config
|
|
121
|
-
@templates_dir = templates_dir
|
|
122
|
-
@output_dir = output_dir
|
|
123
|
-
@update_mode = update_mode
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
# Renders all templates into the output directory.
|
|
127
|
-
def render_all
|
|
128
|
-
FileUtils.mkdir_p(@output_dir)
|
|
129
|
-
|
|
130
|
-
render_template(".gitignore.erb", ".gitignore")
|
|
131
|
-
render_template(".pre-commit-config.yaml.erb", ".pre-commit-config.yaml")
|
|
132
|
-
render_template(".rubocop.yml.erb", ".rubocop.yml")
|
|
133
|
-
render_template("AGENTS.md.erb", "AGENTS.md")
|
|
134
|
-
render_template("CHANGELOG.md.erb", "CHANGELOG.md") unless @update_mode
|
|
135
|
-
render_template("CONTRIBUTING.md.erb", "CONTRIBUTING.md")
|
|
136
|
-
render_template("CODE_OF_CONDUCT.md.erb", "CODE_OF_CONDUCT.md")
|
|
137
|
-
render_template("Gemfile.erb", "Gemfile")
|
|
138
|
-
render_template("README.md.erb", "README.md")
|
|
139
|
-
render_template("REUSE.toml.erb", "REUSE.toml")
|
|
140
|
-
render_template("Rakefile.erb", "Rakefile")
|
|
141
|
-
render_template("gemspec.erb", "#{@config.gem_name}.gemspec")
|
|
142
|
-
render_template("mise.toml.erb", "mise.toml")
|
|
143
|
-
|
|
144
|
-
# bin/ scripts
|
|
145
|
-
render_template("bin/setup.erb", "bin/setup", executable: true)
|
|
146
|
-
render_template("bin/setup.ps1.erb", "bin/setup.ps1")
|
|
147
|
-
render_template("bin/console.erb", "bin/console", executable: true)
|
|
148
|
-
|
|
149
|
-
# GitHub Actions CI workflow
|
|
150
|
-
render_template(".github/workflows/ci.yml.erb", ".github/workflows/ci.yml")
|
|
151
|
-
|
|
152
|
-
# GitHub Actions build-gems workflow (Rust only)
|
|
153
|
-
render_template(".github/workflows/build-gems.yml.erb", ".github/workflows/build-gems.yml") if @config.has_rust
|
|
154
|
-
|
|
155
|
-
# task resources
|
|
156
|
-
copy_task_resources
|
|
157
|
-
|
|
158
|
-
# doc files (RDoc styling)
|
|
159
|
-
copy_doc_files
|
|
160
|
-
|
|
161
|
-
# lib/ structure
|
|
162
|
-
create_lib_structure
|
|
163
|
-
|
|
164
|
-
# Rust extension (if enabled)
|
|
165
|
-
create_rust_extension if @config.has_rust
|
|
166
|
-
|
|
167
|
-
puts "Scaffolded #{@config.gem_name} in #{@output_dir}"
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
private def render_template(template_name, output_name, executable: false)
|
|
171
|
-
template_path = File.join(@templates_dir, template_name)
|
|
172
|
-
output_path = File.join(@output_dir, output_name)
|
|
173
|
-
|
|
174
|
-
FileUtils.mkdir_p(File.dirname(output_path))
|
|
175
|
-
|
|
176
|
-
unless File.exist?(template_path)
|
|
177
|
-
warn " WARNING: Template not found: #{template_name}"
|
|
178
|
-
return
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
content = if template_name.end_with?(".erb")
|
|
182
|
-
ERB.new(File.read(template_path), trim_mode: "-").result(binding_for_config)
|
|
183
|
-
else
|
|
184
|
-
File.read(template_path)
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
if @update_mode && File.exist?(output_path)
|
|
188
|
-
existing = File.read(output_path)
|
|
189
|
-
if existing == content
|
|
190
|
-
puts " Unchanged #{output_name}"
|
|
191
|
-
return
|
|
192
|
-
end
|
|
193
|
-
puts " Conflict #{output_name}"
|
|
194
|
-
show_diff(output_path, content)
|
|
195
|
-
print " Overwrite #{output_name}? [y/N] "
|
|
196
|
-
answer = $stdin.gets&.strip
|
|
197
|
-
unless answer&.match?(/^[Yy]/)
|
|
198
|
-
puts " Skipped #{output_name}"
|
|
199
|
-
return
|
|
200
|
-
end
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
File.write(output_path, content)
|
|
204
|
-
FileUtils.chmod(0o755, output_path) if executable
|
|
205
|
-
puts " Created #{output_name}"
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
private def show_diff(existing_path, new_content)
|
|
209
|
-
require "tempfile"
|
|
210
|
-
Tempfile.create(["scaffold", File.extname(existing_path)]) do |tmp|
|
|
211
|
-
tmp.write(new_content)
|
|
212
|
-
tmp.flush
|
|
213
|
-
system("git", "--no-pager", "diff", "--no-index", "--color", existing_path, tmp.path)
|
|
214
|
-
end
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
private def copy_task_resources
|
|
218
|
-
resources_dir = File.join(@output_dir, "tasks", "resources")
|
|
219
|
-
tasks_dir = File.join(@output_dir, "tasks")
|
|
220
|
-
FileUtils.mkdir_p(resources_dir)
|
|
221
|
-
|
|
222
|
-
# Render ERB templates to tasks/resources/
|
|
223
|
-
render_template("tasks/resources/rubies.yml.erb", "tasks/resources/rubies.yml")
|
|
224
|
-
render_template("tasks/resources/index.html.erb", "tasks/resources/index.html.erb")
|
|
225
|
-
|
|
226
|
-
# Render example_viewer.html.erb to tasks/
|
|
227
|
-
render_template("tasks/example_viewer.html.erb", "tasks/example_viewer.html.erb")
|
|
228
|
-
|
|
229
|
-
# Create exe/.gitkeep
|
|
230
|
-
exe_dir = File.join(@output_dir, "exe")
|
|
231
|
-
FileUtils.mkdir_p(exe_dir)
|
|
232
|
-
gitkeep = File.join(exe_dir, ".gitkeep")
|
|
233
|
-
FileUtils.touch(gitkeep)
|
|
234
|
-
puts " Created exe/.gitkeep"
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
private def copy_doc_files
|
|
238
|
-
doc_dir = File.join(@output_dir, "doc")
|
|
239
|
-
FileUtils.mkdir_p(doc_dir)
|
|
240
|
-
FileUtils.mkdir_p(File.join(doc_dir, "getting_started"))
|
|
241
|
-
FileUtils.mkdir_p(File.join(doc_dir, "concepts"))
|
|
242
|
-
FileUtils.mkdir_p(File.join(doc_dir, "images"))
|
|
243
|
-
|
|
244
|
-
# Render custom.css (now an ERB template)
|
|
245
|
-
render_template("doc/custom.css.erb", "doc/custom.css")
|
|
246
|
-
|
|
247
|
-
# Create images/.gitkeep
|
|
248
|
-
FileUtils.touch(File.join(doc_dir, "images", ".gitkeep"))
|
|
249
|
-
puts " Created doc/images/.gitkeep"
|
|
250
|
-
|
|
251
|
-
# Render doc templates
|
|
252
|
-
render_template("doc/index.md.erb", "doc/index.md")
|
|
253
|
-
render_template("doc/getting_started/quickstart.md.erb", "doc/getting_started/quickstart.md")
|
|
254
|
-
render_template("doc/concepts/application_architecture.md.erb", "doc/concepts/application_architecture.md")
|
|
255
|
-
render_template("doc/concepts/application_testing.md.erb", "doc/concepts/application_testing.md")
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
private def create_lib_structure
|
|
259
|
-
lib_path = File.join(@output_dir, "lib", @config.require_path)
|
|
260
|
-
FileUtils.mkdir_p(lib_path)
|
|
261
|
-
|
|
262
|
-
# RuboCop config shipped inside the gem (resolved via inherit_gem)
|
|
263
|
-
render_template("lib/rubocop.yml", "lib/#{@config.require_path}/rubocop.yml")
|
|
264
|
-
|
|
265
|
-
# Main require file
|
|
266
|
-
render_template("lib/main.rb.erb", "lib/#{@config.require_path}.rb")
|
|
267
|
-
|
|
268
|
-
# Version file
|
|
269
|
-
render_template("lib/version.rb.erb", "lib/#{@config.require_path}/version.rb")
|
|
270
|
-
|
|
271
|
-
# Test helper shipped inside the gem
|
|
272
|
-
render_template("lib/test_helper.rb.erb", "lib/#{@config.require_path}/test_helper.rb")
|
|
273
|
-
|
|
274
|
-
# Test directory with placeholder
|
|
275
|
-
FileUtils.mkdir_p(File.join(@output_dir, "test"))
|
|
276
|
-
render_template("test/test_helper.rb.erb", "test/test_helper.rb")
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
private def create_rust_extension
|
|
280
|
-
ext_name = @config.gem_name.tr("-", "_")
|
|
281
|
-
|
|
282
|
-
render_template("ext/Cargo.toml.erb", "ext/#{ext_name}/Cargo.toml")
|
|
283
|
-
render_template("ext/extconf.rb.erb", "ext/#{ext_name}/extconf.rb")
|
|
284
|
-
render_template("ext/.cargo/config.toml.erb", "ext/#{ext_name}/.cargo/config.toml")
|
|
285
|
-
render_template("ext/.gitignore.erb", "ext/#{ext_name}/.gitignore")
|
|
286
|
-
render_template("ext/clippy.toml.erb", "ext/#{ext_name}/clippy.toml")
|
|
287
|
-
render_template("ext/src/lib.rs.erb", "ext/#{ext_name}/src/lib.rs")
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
private def generate_nested_module(parts, content, indent = 0, is_outermost = true)
|
|
291
|
-
return content if parts.empty?
|
|
292
|
-
|
|
293
|
-
prefix = " " * indent
|
|
294
|
-
first, *rest = parts
|
|
295
|
-
inner = generate_nested_module(rest, content, indent + 1, false)
|
|
296
|
-
inner_prefix = " " * (indent + 1)
|
|
297
|
-
|
|
298
|
-
if rest.empty?
|
|
299
|
-
# Innermost module - content is a doc comment that goes BEFORE the module
|
|
300
|
-
if content.empty?
|
|
301
|
-
"#{prefix}module #{first}\n#{prefix}end"
|
|
302
|
-
else
|
|
303
|
-
"#{prefix}#{content}\n#{prefix}module #{first}\n#{prefix}end"
|
|
304
|
-
end
|
|
305
|
-
else
|
|
306
|
-
# Outer modules get :nodoc: to avoid "missing documentation" warnings
|
|
307
|
-
# (they're documented in the main require file or the core gem)
|
|
308
|
-
nodoc = is_outermost ? " # :nodoc: Documented in the ratatui_ruby gem." : ""
|
|
309
|
-
"#{prefix}module #{first}#{nodoc}\n#{inner}\n#{prefix}end"
|
|
310
|
-
end
|
|
311
|
-
end
|
|
312
|
-
|
|
313
|
-
private def generate_nested_module_with_error(parts, indent = 0)
|
|
314
|
-
prefix = " " * indent
|
|
315
|
-
if parts.length == 1
|
|
316
|
-
# Innermost module with documented Error class
|
|
317
|
-
<<~RUBY.chomp
|
|
318
|
-
#{prefix}module #{parts.first}
|
|
319
|
-
#{prefix} # Base error class for this library.
|
|
320
|
-
#{prefix} #
|
|
321
|
-
#{prefix} # All library-specific exceptions inherit from this class.
|
|
322
|
-
#{prefix} # Catch this to handle any library error generically.
|
|
323
|
-
#{prefix} class Error < StandardError; end
|
|
324
|
-
#{prefix}end
|
|
325
|
-
RUBY
|
|
326
|
-
else
|
|
327
|
-
first, *rest = parts
|
|
328
|
-
inner = generate_nested_module_with_error(rest, indent + 1)
|
|
329
|
-
"#{prefix}module #{first}\n#{inner}\n#{prefix}end"
|
|
330
|
-
end
|
|
331
|
-
end
|
|
332
|
-
|
|
333
|
-
private def generate_nested_module_with_version(parts, indent = 0, is_outermost = true)
|
|
334
|
-
prefix = " " * indent
|
|
335
|
-
if parts.length == 1
|
|
336
|
-
# Innermost module with documented VERSION constant
|
|
337
|
-
<<~RUBY.chomp
|
|
338
|
-
#{prefix}module #{parts.first}
|
|
339
|
-
#{prefix} # The version of this gem.
|
|
340
|
-
#{prefix} # See https://semver.org/spec/v2.0.0.html
|
|
341
|
-
#{prefix} VERSION = "0.0.1.pre.1"
|
|
342
|
-
#{prefix}end
|
|
343
|
-
RUBY
|
|
344
|
-
else
|
|
345
|
-
first, *rest = parts
|
|
346
|
-
inner = generate_nested_module_with_version(rest, indent + 1, false)
|
|
347
|
-
# Outer modules get :nodoc: to avoid "missing documentation" warnings
|
|
348
|
-
# (they're documented in the main require file or the core gem)
|
|
349
|
-
nodoc = is_outermost ? " # :nodoc: Documented in the ratatui_ruby gem." : ""
|
|
350
|
-
"#{prefix}module #{first}#{nodoc}\n#{inner}\n#{prefix}end"
|
|
351
|
-
end
|
|
352
|
-
end
|
|
353
|
-
|
|
354
|
-
private def binding_for_config
|
|
355
|
-
module_parts = @config.module_name.split("::")
|
|
356
|
-
ext_name = @config.gem_name.tr("-", "_")
|
|
357
|
-
|
|
358
|
-
# Create a binding with all config values available to templates
|
|
359
|
-
b = binding
|
|
360
|
-
b.local_variable_set(:gem_name, @config.gem_name)
|
|
361
|
-
b.local_variable_set(:gem_display_name, @config.module_name)
|
|
362
|
-
b.local_variable_set(:module_name, @config.module_name)
|
|
363
|
-
b.local_variable_set(:require_path, @config.require_path)
|
|
364
|
-
b.local_variable_set(:copyright_holder, @config.copyright_holder)
|
|
365
|
-
b.local_variable_set(:license, @config.license)
|
|
366
|
-
b.local_variable_set(:author, @config.author)
|
|
367
|
-
b.local_variable_set(:email, @config.email)
|
|
368
|
-
b.local_variable_set(:year, @config.year)
|
|
369
|
-
b.local_variable_set(:has_rdoc, true)
|
|
370
|
-
b.local_variable_set(:has_rust, @config.has_rust)
|
|
371
|
-
b.local_variable_set(:rubies, @config.ruby_versions)
|
|
372
|
-
b.local_variable_set(:ext_name, ext_name)
|
|
373
|
-
b.local_variable_set(:nested_module, generate_nested_module(module_parts, "# Namespace for library functionality."))
|
|
374
|
-
b.local_variable_set(:nested_module_with_version, generate_nested_module_with_version(module_parts))
|
|
375
|
-
b.local_variable_set(:update_mode, @update_mode)
|
|
376
|
-
b.local_variable_set(:dependencies, [])
|
|
377
|
-
b.local_variable_set(:summary, "Part of the RatatuiRuby ecosystem")
|
|
378
|
-
b.local_variable_set(:description, "#{@config.module_name} - part of the RatatuiRuby TUI framework ecosystem")
|
|
379
|
-
b.local_variable_set(:github_repo, "setdef/#{@config.module_name}")
|
|
380
|
-
b.local_variable_set(:project_name, @config.module_name)
|
|
381
|
-
b.local_variable_set(:version_file_require, "lib/#{@config.require_path}/version")
|
|
382
|
-
b.local_variable_set(:version_file, "lib/#{@config.require_path}/version.rb")
|
|
383
|
-
b
|
|
384
|
-
end
|
|
385
|
-
end
|
|
48
|
+
require_relative "../lib/ratatui_ruby/devtools/scaffold/scaffold_config"
|
|
49
|
+
require_relative "../lib/ratatui_ruby/devtools/scaffold/template_renderer"
|
|
386
50
|
|
|
387
51
|
# Parse command line options
|
|
388
52
|
config = ScaffoldConfig.new
|
|
@@ -533,11 +197,13 @@ else
|
|
|
533
197
|
system("git commit --allow-empty -m 'chore: scaffold #{config.gem_name} with ratatui_ruby-devtools'")
|
|
534
198
|
end
|
|
535
199
|
|
|
536
|
-
# Create tag and stable branch
|
|
537
|
-
|
|
200
|
+
# Create tag and stable branch. A gem in initial development still makes
|
|
201
|
+
# normal releases; a prerelease is a candidate users must opt into, so the
|
|
202
|
+
# gem starts at 0.0.0 rather than at a prerelease of 0.0.1.
|
|
203
|
+
system("git tag v0.0.0 -m 'Initial scaffold release'")
|
|
538
204
|
system("git branch stable")
|
|
539
205
|
puts " Created branches: trunk (default), stable"
|
|
540
|
-
puts " Created tag: v0.0.
|
|
206
|
+
puts " Created tag: v0.0.0"
|
|
541
207
|
end
|
|
542
208
|
|
|
543
209
|
puts ""
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
6
|
+
#++
|
|
7
|
+
|
|
8
|
+
# Configuration for scaffold generation.
|
|
9
|
+
#
|
|
10
|
+
# Holds all parameters needed to render templates. Auto-discovers author info
|
|
11
|
+
# from git config if not provided.
|
|
12
|
+
class ScaffoldConfig
|
|
13
|
+
# The gem name to scaffold.
|
|
14
|
+
attr_accessor :gem_name
|
|
15
|
+
|
|
16
|
+
# The copyright holder's name.
|
|
17
|
+
attr_accessor :author
|
|
18
|
+
|
|
19
|
+
# The copyright holder's email.
|
|
20
|
+
attr_accessor :email
|
|
21
|
+
|
|
22
|
+
# The SPDX license identifier.
|
|
23
|
+
attr_accessor :license
|
|
24
|
+
|
|
25
|
+
# The output directory path.
|
|
26
|
+
attr_accessor :output_dir
|
|
27
|
+
|
|
28
|
+
# Whether this gem includes a Rust native extension.
|
|
29
|
+
attr_accessor :has_rust
|
|
30
|
+
|
|
31
|
+
# Creates a new config with defaults from git.
|
|
32
|
+
#
|
|
33
|
+
# Reads author name and email from git config. Sets default license to
|
|
34
|
+
# LGPL-3.0-or-later. Override any accessor after creation.
|
|
35
|
+
def initialize
|
|
36
|
+
@license = "LGPL-3.0-or-later"
|
|
37
|
+
@author = `git config user.name`.strip
|
|
38
|
+
@email = `git config user.email`.strip
|
|
39
|
+
@has_rust = false
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# The gem name with underscores (for module names).
|
|
43
|
+
def module_name
|
|
44
|
+
gem_name.split("-").map { |s| s.split("_").map(&:capitalize).join }.join("::")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# The gem name with slashes (for require paths).
|
|
48
|
+
def require_path
|
|
49
|
+
gem_name.tr("-", "/")
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Copyright holder string for SPDX headers.
|
|
53
|
+
def copyright_holder
|
|
54
|
+
"#{author} <#{email}>"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Current year for copyright.
|
|
58
|
+
def year
|
|
59
|
+
Time.now.year
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Ruby versions to test in CI. Each names a minor version, so CI tests its
|
|
63
|
+
# newest patch release.
|
|
64
|
+
def ruby_versions
|
|
65
|
+
%w[3.3 3.4 4.0]
|
|
66
|
+
end
|
|
67
|
+
end
|