ukiryu 0.1.1 → 0.1.3

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.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +58 -14
  3. data/.gitignore +3 -0
  4. data/.rubocop_todo.yml +170 -79
  5. data/Gemfile +1 -1
  6. data/README.adoc +1603 -576
  7. data/docs/.gitignore +1 -0
  8. data/docs/Gemfile +10 -0
  9. data/docs/INDEX.adoc +261 -0
  10. data/docs/_config.yml +180 -0
  11. data/docs/advanced/custom-tool-classes.adoc +581 -0
  12. data/docs/advanced/index.adoc +20 -0
  13. data/docs/features/configuration.adoc +657 -0
  14. data/docs/features/index.adoc +31 -0
  15. data/docs/features/platform-support.adoc +488 -0
  16. data/docs/getting-started/core-concepts.adoc +666 -0
  17. data/docs/getting-started/index.adoc +36 -0
  18. data/docs/getting-started/installation.adoc +216 -0
  19. data/docs/getting-started/quick-start.adoc +258 -0
  20. data/docs/guides/env-var-sets.adoc +388 -0
  21. data/docs/guides/index.adoc +20 -0
  22. data/docs/interfaces/cli.adoc +609 -0
  23. data/docs/interfaces/index.adoc +153 -0
  24. data/docs/interfaces/ruby-api.adoc +538 -0
  25. data/docs/lychee.toml +49 -0
  26. data/docs/reference/configuration-options.adoc +720 -0
  27. data/docs/reference/error-codes.adoc +634 -0
  28. data/docs/reference/index.adoc +20 -0
  29. data/docs/reference/ruby-api.adoc +1217 -0
  30. data/docs/understanding/index.adoc +20 -0
  31. data/lib/ukiryu/cli.rb +43 -58
  32. data/lib/ukiryu/cli_commands/base_command.rb +16 -27
  33. data/lib/ukiryu/cli_commands/cache_command.rb +100 -0
  34. data/lib/ukiryu/cli_commands/commands_command.rb +8 -8
  35. data/lib/ukiryu/cli_commands/commands_command.rb.fixed +1 -1
  36. data/lib/ukiryu/cli_commands/config_command.rb +49 -7
  37. data/lib/ukiryu/cli_commands/definitions_command.rb +254 -0
  38. data/lib/ukiryu/cli_commands/describe_command.rb +13 -7
  39. data/lib/ukiryu/cli_commands/describe_command.rb.fixed +1 -1
  40. data/lib/ukiryu/cli_commands/docs_command.rb +148 -0
  41. data/lib/ukiryu/cli_commands/exec_inline_command.rb.fixed +1 -1
  42. data/lib/ukiryu/cli_commands/extract_command.rb +2 -2
  43. data/lib/ukiryu/cli_commands/info_command.rb +7 -7
  44. data/lib/ukiryu/cli_commands/lint_command.rb +167 -0
  45. data/lib/ukiryu/cli_commands/list_command.rb +6 -6
  46. data/lib/ukiryu/cli_commands/opts_command.rb +2 -2
  47. data/lib/ukiryu/cli_commands/opts_command.rb.fixed +1 -1
  48. data/lib/ukiryu/cli_commands/register_command.rb +144 -0
  49. data/lib/ukiryu/cli_commands/resolve_command.rb +124 -0
  50. data/lib/ukiryu/cli_commands/run_command.rb +38 -14
  51. data/lib/ukiryu/cli_commands/run_file_command.rb +2 -2
  52. data/lib/ukiryu/cli_commands/system_command.rb +50 -32
  53. data/lib/ukiryu/cli_commands/validate_command.rb +452 -51
  54. data/lib/ukiryu/cli_commands/which_command.rb +5 -5
  55. data/lib/ukiryu/command_builder.rb +81 -23
  56. data/lib/ukiryu/config/env_provider.rb +3 -3
  57. data/lib/ukiryu/config/env_schema.rb +6 -6
  58. data/lib/ukiryu/config.rb +11 -11
  59. data/lib/ukiryu/definition/definition_cache.rb +238 -0
  60. data/lib/ukiryu/definition/definition_composer.rb +257 -0
  61. data/lib/ukiryu/definition/definition_linter.rb +460 -0
  62. data/lib/ukiryu/definition/definition_validator.rb +320 -0
  63. data/lib/ukiryu/definition/discovery.rb +239 -0
  64. data/lib/ukiryu/definition/documentation_generator.rb +429 -0
  65. data/lib/ukiryu/definition/lint_issue.rb +168 -0
  66. data/lib/ukiryu/definition/loader.rb +139 -0
  67. data/lib/ukiryu/definition/metadata.rb +159 -0
  68. data/lib/ukiryu/definition/source.rb +87 -0
  69. data/lib/ukiryu/definition/sources/file.rb +138 -0
  70. data/lib/ukiryu/definition/sources/string.rb +88 -0
  71. data/lib/ukiryu/definition/validation_result.rb +158 -0
  72. data/lib/ukiryu/definition/version_resolver.rb +194 -0
  73. data/lib/ukiryu/definition.rb +40 -0
  74. data/lib/ukiryu/errors.rb +6 -0
  75. data/lib/ukiryu/execution_context.rb +11 -11
  76. data/lib/ukiryu/executor.rb +6 -0
  77. data/lib/ukiryu/extractors/extractor.rb +6 -5
  78. data/lib/ukiryu/extractors/help_parser.rb +13 -19
  79. data/lib/ukiryu/logger.rb +3 -1
  80. data/lib/ukiryu/models/command_definition.rb +3 -3
  81. data/lib/ukiryu/models/command_info.rb +1 -1
  82. data/lib/ukiryu/models/components.rb +1 -3
  83. data/lib/ukiryu/models/env_var_definition.rb +11 -3
  84. data/lib/ukiryu/models/flag_definition.rb +15 -0
  85. data/lib/ukiryu/models/option_definition.rb +7 -7
  86. data/lib/ukiryu/models/platform_profile.rb +6 -3
  87. data/lib/ukiryu/models/routing.rb +1 -1
  88. data/lib/ukiryu/models/tool_definition.rb +2 -4
  89. data/lib/ukiryu/models/tool_metadata.rb +6 -6
  90. data/lib/ukiryu/models/validation_result.rb +1 -1
  91. data/lib/ukiryu/models/version_compatibility.rb +6 -3
  92. data/lib/ukiryu/models/version_detection.rb +10 -1
  93. data/lib/ukiryu/{registry.rb → register.rb} +54 -38
  94. data/lib/ukiryu/register_auto_manager.rb +268 -0
  95. data/lib/ukiryu/schema_validator.rb +31 -10
  96. data/lib/ukiryu/shell/base.rb +18 -0
  97. data/lib/ukiryu/shell/bash.rb +19 -1
  98. data/lib/ukiryu/shell/cmd.rb +11 -1
  99. data/lib/ukiryu/shell/powershell.rb +11 -1
  100. data/lib/ukiryu/shell.rb +1 -1
  101. data/lib/ukiryu/tool.rb +107 -95
  102. data/lib/ukiryu/tool_index.rb +22 -22
  103. data/lib/ukiryu/tools/base.rb +12 -25
  104. data/lib/ukiryu/tools/generator.rb +7 -7
  105. data/lib/ukiryu/tools.rb +3 -3
  106. data/lib/ukiryu/type.rb +20 -5
  107. data/lib/ukiryu/version.rb +1 -1
  108. data/lib/ukiryu/version_detector.rb +21 -2
  109. data/lib/ukiryu.rb +6 -3
  110. data/ukiryu-proposal.md +41 -41
  111. data/ukiryu.gemspec +1 -0
  112. metadata +64 -8
  113. data/.gitmodules +0 -3
@@ -0,0 +1,254 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../definition'
4
+
5
+ module Ukiryu
6
+ module CliCommands
7
+ # CLI commands for managing tool definitions
8
+ #
9
+ # This command group provides functionality for:
10
+ # - Listing discovered definitions
11
+ # - Showing definition search paths
12
+ # - Adding definitions to the user library
13
+ # - Removing definitions from the user library
14
+ # - Showing details about specific definitions
15
+ class DefinitionsCommand < Thor
16
+ default_command :list
17
+
18
+ # List all discovered definitions
19
+ #
20
+ # @param verbose [Boolean] show detailed information
21
+ desc 'list', 'List all discovered definitions'
22
+ method_option :verbose, aliases: :v, desc: 'Show detailed information', type: :boolean, default: false
23
+ def list
24
+ definitions = Definition::Discovery.discover
25
+
26
+ if definitions.empty?
27
+ puts 'No definitions found.'
28
+ puts
29
+ puts 'Search paths:'
30
+ Definition::Discovery.search_paths.each do |path|
31
+ puts " - #{path}"
32
+ end
33
+ return
34
+ end
35
+
36
+ if options[:verbose]
37
+ # Verbose output with details
38
+ definitions.each do |tool_name, defs|
39
+ puts "#{tool_name}:"
40
+ defs.each do |metadata|
41
+ priority_indicator = defs.index(metadata).zero? ? '*' : ' '
42
+ puts " #{priority_indicator} #{metadata.version} (#{metadata.source_type})"
43
+ puts " Path: #{metadata.path}"
44
+ end
45
+ puts
46
+ end
47
+ else
48
+ # Simple output
49
+ definitions.each do |tool_name, defs|
50
+ best = defs.first
51
+ versions_str = defs.map(&:version).join(', ')
52
+ puts "#{tool_name}: #{versions_str} [#{best.source_type}]"
53
+ end
54
+ end
55
+
56
+ puts "\nLegend: * = highest priority (will be used by default)"
57
+ end
58
+
59
+ # Show definition search paths
60
+ #
61
+ desc 'path', 'Show definition search paths'
62
+ def path
63
+ puts 'Definition search paths (in priority order):'
64
+ puts
65
+
66
+ paths = Definition::Discovery.search_paths
67
+ paths.each_with_index do |path, index|
68
+ prefix = index.zero? ? '(1) [Highest Priority]' : "(#{index + 1})"
69
+ exists = File.directory?(path) ? '✓' : '✗'
70
+ puts "#{prefix} #{exists} #{path}"
71
+ end
72
+
73
+ puts
74
+ puts "User directory: #{Definition::Discovery.user_definitions_directory}"
75
+ puts "XDG_DATA_HOME: #{Definition::Discovery.xdg_data_home}"
76
+ puts "XDG_DATA_DIRS: #{Definition::Discovery.xdg_data_dirs.join(':')}"
77
+ end
78
+
79
+ # Add a definition to the user library
80
+ #
81
+ # @param source_path [String] path to the definition file to add
82
+ desc 'add SOURCE', 'Add definition to user library'
83
+ method_option :name, aliases: :n, desc: 'Tool name (auto-detected from file if not specified)', type: :string
84
+ method_option :version, aliases: :V, desc: 'Version (auto-detected from file if not specified)', type: :string
85
+ def add(source_path)
86
+ source_path = File.expand_path(source_path)
87
+
88
+ unless File.exist?(source_path)
89
+ warn "Error: Source file not found: #{source_path}"
90
+ exit 1
91
+ end
92
+
93
+ # Load the definition to get metadata
94
+ begin
95
+ metadata = Definition::Loader.load_from_file(source_path, validation: :strict)
96
+ rescue DefinitionLoadError, DefinitionValidationError => e
97
+ warn "Error: Failed to load definition: #{e.message}"
98
+ exit 1
99
+ end
100
+
101
+ tool_name = options[:name] || metadata.name
102
+ version = options[:version] || metadata.version || '1.0'
103
+
104
+ # Determine target directory
105
+ user_dir = Definition::Discovery.user_definitions_directory
106
+ tool_dir = File.join(user_dir, tool_name)
107
+
108
+ # Create directories if needed
109
+ FileUtils.mkdir_p(tool_dir)
110
+
111
+ # Target file path
112
+ target_path = File.join(tool_dir, "#{version}.yaml")
113
+
114
+ # Check if target already exists
115
+ if File.exist?(target_path)
116
+ warn "Error: Definition already exists: #{target_path}"
117
+ warn 'Use --name and --version to specify a different tool/version.'
118
+ exit 1
119
+ end
120
+
121
+ # Copy the definition
122
+ FileUtils.cp(source_path, target_path)
123
+
124
+ puts 'Definition added successfully:'
125
+ puts " Tool: #{tool_name}"
126
+ puts " Version: #{version}"
127
+ puts " Location: #{target_path}"
128
+ end
129
+
130
+ # Remove a definition from the user library
131
+ #
132
+ # @param tool_name [String] the tool name
133
+ desc 'remove TOOL', 'Remove definition from user library'
134
+ method_option :version, aliases: :v, desc: 'Specific version to remove (removes all if not specified)',
135
+ type: :string
136
+ method_option :force, aliases: :f, desc: 'Skip confirmation prompt', type: :boolean, default: false
137
+ def remove(tool_name)
138
+ user_dir = Definition::Discovery.user_definitions_directory
139
+ tool_dir = File.join(user_dir, tool_name)
140
+
141
+ unless File.directory?(tool_dir)
142
+ warn "Error: No definitions found for tool '#{tool_name}'"
143
+ warn "User definitions directory: #{user_dir}"
144
+ exit 1
145
+ end
146
+
147
+ # Find versions to remove
148
+ versions = if options[:version]
149
+ specific_file = File.join(tool_dir, "#{options[:version]}.yaml")
150
+ if File.exist?(specific_file)
151
+ [options[:version]]
152
+ else
153
+ warn "Error: Version #{options[:version]} not found for tool '#{tool_name}'"
154
+ exit 1
155
+ end
156
+ else
157
+ # Get all versions
158
+ Dir.glob(File.join(tool_dir, '*.yaml')).map do |file|
159
+ File.basename(file, '.yaml')
160
+ end
161
+ end
162
+
163
+ # Confirm removal
164
+ unless options[:force]
165
+ puts 'This will remove the following definitions:'
166
+ versions.each do |v|
167
+ puts " - #{tool_name}/#{v}"
168
+ end
169
+ print 'Are you sure? [y/N] '
170
+ response = $stdin.gets.chomp
171
+ unless response.downcase == 'y'
172
+ puts 'Cancelled.'
173
+ return
174
+ end
175
+ end
176
+
177
+ # Remove files
178
+ versions.each do |v|
179
+ file_path = File.join(tool_dir, "#{v}.yaml")
180
+ FileUtils.rm(file_path)
181
+ puts "Removed: #{tool_name}/#{v}"
182
+ end
183
+
184
+ # Remove tool directory if empty
185
+ if Dir.empty?(tool_dir)
186
+ FileUtils.rmdir(tool_dir)
187
+ puts "Removed empty directory: #{tool_dir}"
188
+ end
189
+
190
+ puts 'Done.'
191
+ end
192
+
193
+ # Show details about a specific definition
194
+ #
195
+ # @param tool_name [String] the tool name
196
+ desc 'info TOOL', 'Show definition details'
197
+ method_option :version, aliases: :v, desc: 'Specific version to show (shows best available if not specified)',
198
+ type: :string
199
+ def info(tool_name)
200
+ definitions = Definition::Discovery.definitions_for(tool_name)
201
+
202
+ if definitions.nil? || definitions.empty?
203
+ warn "Error: No definitions found for tool '#{tool_name}'"
204
+ exit 1
205
+ end
206
+
207
+ # Find the requested version or best available
208
+ metadata = if options[:version]
209
+ definitions.find { |d| d.version == options[:version] }
210
+ else
211
+ definitions.first
212
+ end
213
+
214
+ unless metadata
215
+ warn "Error: Version '#{options[:version]}' not found for tool '#{tool_name}'"
216
+ warn "Available versions: #{definitions.map(&:version).join(', ')}"
217
+ exit 1
218
+ end
219
+
220
+ # Show details
221
+ puts "Tool: #{metadata.name}"
222
+ puts "Version: #{metadata.version}"
223
+ puts "Source: #{metadata.source_type}"
224
+ puts "Path: #{metadata.path}"
225
+ puts "Exists: #{metadata.exists? ? 'Yes' : 'No'}"
226
+ puts "Modified: #{metadata.mtime}" if metadata.exists?
227
+
228
+ # Show all available versions
229
+ if definitions.length > 1
230
+ puts
231
+ puts 'Available versions:'
232
+ definitions.each do |defn|
233
+ current = defn.version == metadata.version
234
+ indicator = current ? '*' : ' '
235
+ priority_note = defn == definitions.first ? ' [default]' : ''
236
+ puts " #{indicator} #{defn.version} (#{defn.source_type})#{priority_note}"
237
+ end
238
+ end
239
+
240
+ # Try to load and validate the definition
241
+ puts
242
+ begin
243
+ tool_def = metadata.load_definition
244
+ puts 'Validation: ✓ Valid'
245
+ puts "Display Name: #{tool_def.display_name}" if tool_def.display_name
246
+ puts "Homepage: #{tool_def.homepage}" if tool_def.homepage
247
+ rescue DefinitionLoadError, DefinitionValidationError => e
248
+ puts 'Validation: ✗ Invalid'
249
+ puts "Error: #{e.message}"
250
+ end
251
+ end
252
+ end
253
+ end
254
+ end
@@ -12,11 +12,11 @@ module Ukiryu
12
12
  # @param tool_name [String] the tool name
13
13
  # @param command_name [String, nil] optional command name
14
14
  def run(tool_name, command_name = nil)
15
- setup_registry
15
+ setup_register
16
16
 
17
17
  # Use find_by for interface-based discovery (ping -> ping_bsd/ping_gnu)
18
18
  tool = Tool.find_by(tool_name.to_sym)
19
- error!("Tool not found: #{tool_name}\nAvailable tools: #{Registry.tools.sort.join(', ')}") unless tool
19
+ error!("Tool not found: #{tool_name}\nAvailable tools: #{Register.tools.sort.join(', ')}") unless tool
20
20
 
21
21
  tool_commands = tool.commands
22
22
  error! "No commands defined for #{tool_name}" unless tool_commands
@@ -78,6 +78,9 @@ module Ukiryu
78
78
 
79
79
  # Show usage if available
80
80
  say " Usage: #{cmd.usage}", :dim if cmd.usage
81
+
82
+ # Show env var sets if available
83
+ say " Env Var Sets: #{cmd.use_env_vars.join(', ')}", :dim if cmd.use_env_vars && !cmd.use_env_vars.empty?
81
84
  end
82
85
 
83
86
  say '', :clear
@@ -123,6 +126,9 @@ module Ukiryu
123
126
  cmd_display = (cmd.name || 'unnamed').to_s.ljust(20)
124
127
  desc_display = cmd.description || 'No description'
125
128
  say " #{cmd_display} #{desc_display}", :white
129
+
130
+ # Show env var sets if available
131
+ say " Env Var Sets: #{cmd.use_env_vars.join(', ')}", :dim if cmd.use_env_vars && !cmd.use_env_vars.empty?
126
132
  end
127
133
 
128
134
  say '', :clear
@@ -154,9 +160,9 @@ module Ukiryu
154
160
  say '', :clear
155
161
  end
156
162
 
157
- # Execution mode
158
- if cmd.execution_mode
159
- say "Execution Mode: #{cmd.execution_mode}", :white
163
+ # Env var sets
164
+ if cmd.use_env_vars && !cmd.use_env_vars.empty?
165
+ say "Env Var Sets: #{cmd.use_env_vars.join(', ')}", :white
160
166
  say '', :clear
161
167
  end
162
168
 
@@ -200,13 +206,13 @@ module Ukiryu
200
206
  name = opt.name || 'unnamed'
201
207
  cli = opt.cli || 'N/A'
202
208
  type = opt.type || 'string'
203
- format = opt.format || 'N/A'
209
+ assignment_delimiter = opt.assignment_delimiter || 'auto'
204
210
  default = opt.default
205
211
  platforms = opt.platforms || []
206
212
 
207
213
  say " #{name} (#{type})", :white
208
214
  say " CLI: #{cli}", :dim
209
- say " Format: #{format}", :dim if format != 'N/A'
215
+ say " Assignment Delimiter: #{assignment_delimiter}", :dim if assignment_delimiter != 'auto'
210
216
  say " Default: #{default}", :dim if default
211
217
  say " Platforms: #{platforms.join(', ')}", :dim if platforms.any?
212
218
  say " Description: #{opt.description}", :dim if opt.description
@@ -12,7 +12,7 @@ module Ukiryu
12
12
  # @param tool_name [String] the tool name
13
13
  # @param command_name [String, nil] optional command name
14
14
  def run(tool_name, command_name = nil)
15
- setup_registry
15
+ setup_register
16
16
 
17
17
  tool = Tool.get(tool_name)
18
18
  tool_commands = tool.commands
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor'
4
+ require_relative '../definition/documentation_generator'
5
+
6
+ module Ukiryu
7
+ module CliCommands
8
+ # Generate documentation from tool definitions
9
+ #
10
+ # The docs command generates human-readable documentation
11
+ # from tool definitions in various formats.
12
+ class DocsCommand < Thor
13
+ class_option :verbose, type: :boolean, default: false
14
+ class_option :format, type: :string, default: 'markdown', enum: %w[markdown md asciidoc adoc]
15
+ class_option :output, type: :string, desc: 'Output file path'
16
+
17
+ desc 'generate TOOL', 'Generate documentation for a tool'
18
+ option :register, type: :string, desc: 'Register path'
19
+ def generate(tool_name)
20
+ generate_docs(tool_name)
21
+ end
22
+
23
+ desc 'generate-all', 'Generate documentation for all tools'
24
+ option :register, type: :string, desc: 'Register path'
25
+ option :output_dir, type: :string, desc: 'Output directory', default: 'docs'
26
+ def generate_all
27
+ generate_all_docs
28
+ end
29
+
30
+ desc 'serve', 'Serve documentation locally (experimental)'
31
+ option :port, type: :numeric, default: 8000
32
+ def serve
33
+ serve_docs
34
+ end
35
+
36
+ private
37
+
38
+ # Generate documentation for a tool
39
+ #
40
+ # @param tool_name [String] the tool name
41
+ def generate_docs(tool_name)
42
+ register_path = options[:register] || Ukiryu::Register.default_register_path
43
+ tool_path = File.join(register_path, 'tools', tool_name)
44
+
45
+ say_error("Tool not found: #{tool_name}") unless Dir.exist?(tool_path)
46
+
47
+ # Find latest version
48
+ version_dirs = Dir.entries(tool_path)
49
+ .reject { |e| e.start_with?('.') }
50
+ .select { |e| File.directory?(File.join(tool_path, e)) }
51
+ .sort { |a, b| Gem::Version.new(b) <=> Gem::Version.new(a) }
52
+
53
+ say_error("No versions found for tool: #{tool_name}") if version_dirs.empty?
54
+
55
+ latest_version = version_dirs.first
56
+ definition_file = Dir.glob(File.join(tool_path, latest_version, '*.yaml')).first
57
+
58
+ say_error("No definition file found for #{tool_name} #{latest_version}") unless definition_file
59
+
60
+ definition = Ukiryu::Definition::Loader.load_from_file(definition_file)
61
+ format = normalize_format
62
+
63
+ begin
64
+ docs = Ukiryu::Definition::DocumentationGenerator.generate(definition, format: format)
65
+ rescue ArgumentError => e
66
+ say_error("Error: #{e.message}")
67
+ end
68
+
69
+ # Output
70
+ if options[:output]
71
+ File.write(options[:output], docs)
72
+ say "✓ Documentation written to: #{options[:output]}", :green
73
+ else
74
+ say docs, :white
75
+ end
76
+ end
77
+
78
+ # Generate documentation for all tools
79
+ def generate_all_docs
80
+ register_path = options[:register] || Ukiryu::Register.default_register_path
81
+ tools_dir = File.join(register_path, 'tools')
82
+
83
+ say_error("Tools directory not found: #{tools_dir}") unless Dir.exist?(tools_dir)
84
+
85
+ output_dir = options[:output_dir]
86
+ FileUtils.mkdir_p(output_dir)
87
+
88
+ count = 0
89
+ Dir.glob(File.join(tools_dir, '*', '*/*.yaml')).each do |file|
90
+ parts = file.split('/')
91
+ tool_name = parts[-3]
92
+ version = parts[-2]
93
+ File.basename(file, '.yaml')
94
+
95
+ definition = Ukiryu::Definition::Loader.load_from_file(file)
96
+ format = normalize_format
97
+
98
+ begin
99
+ docs = Ukiryu::Definition::DocumentationGenerator.generate(definition, format: format)
100
+ rescue ArgumentError => e
101
+ say "Warning: Could not generate docs for #{file}: #{e.message}", :yellow
102
+ next
103
+ end
104
+
105
+ # Write to file
106
+ output_file = File.join(output_dir, "#{tool_name}-#{version}.#{format == :asciidoc ? 'adoc' : 'md'}")
107
+ File.write(output_file, docs)
108
+ count += 1
109
+
110
+ say "✓ Generated: #{output_file}", :green
111
+ end
112
+
113
+ say '', :clear
114
+ say "Generated #{count} documentation file(s) in: #{output_dir}", :cyan
115
+ end
116
+
117
+ # Serve documentation locally
118
+ def serve_docs
119
+ say 'Documentation server is not yet implemented.', :yellow
120
+ say "\nFor now, you can use a simple HTTP server:", :white
121
+ say " python3 -m http.server #{options[:port]}", :dim
122
+ say " ruby -run -e httpd . -p #{options[:port]}", :dim
123
+ end
124
+
125
+ # Normalize format option
126
+ #
127
+ # @return [Symbol] normalized format
128
+ def normalize_format
129
+ case options[:format]
130
+ when 'adoc'
131
+ :asciidoc
132
+ when 'md'
133
+ :markdown
134
+ else
135
+ options[:format].to_sym
136
+ end
137
+ end
138
+
139
+ # Show error message
140
+ #
141
+ # @param message [String] error message
142
+ def say_error(message)
143
+ say message, :red
144
+ exit 1
145
+ end
146
+ end
147
+ end
148
+ end
@@ -18,7 +18,7 @@ module Ukiryu
18
18
  # @param command_name [String] the command name
19
19
  # @param params [Array<String>] key=value parameter pairs
20
20
  def run(tool_name, command_name, *params)
21
- setup_registry
21
+ setup_register
22
22
 
23
23
  # Parse key=value pairs into arguments hash
24
24
  arguments = parse_inline_params(params)
@@ -68,8 +68,8 @@ module Ukiryu
68
68
  if options[:method] && options[:method] != 'auto'
69
69
  say " - #{options[:method]} (explicitly selected)", :white
70
70
  else
71
- say " - native (try --ukiryu-definition flag)", :white
72
- say " - help (parse --help output)", :white
71
+ say ' - native (try --ukiryu-definition flag)', :white
72
+ say ' - help (parse --help output)', :white
73
73
  end
74
74
 
75
75
  say '', :clear
@@ -11,11 +11,11 @@ module Ukiryu
11
11
  #
12
12
  # @param tool_name [String] the tool name
13
13
  def run(tool_name)
14
- setup_registry
14
+ setup_register
15
15
 
16
16
  # Use find_by for interface-based discovery (ping -> ping_bsd/ping_gnu)
17
17
  tool = Tool.find_by(tool_name.to_sym)
18
- error!("Tool not found: #{tool_name}\nAvailable tools: #{Registry.tools.sort.join(', ')}") unless tool
18
+ error!("Tool not found: #{tool_name}\nAvailable tools: #{Register.tools.sort.join(', ')}") unless tool
19
19
 
20
20
  profile = tool.profile
21
21
  show_all = options[:all]
@@ -122,22 +122,22 @@ module Ukiryu
122
122
  # @param current_tool_name [String] the current tool name to exclude
123
123
  # @return [Array<String>] list of other tool names
124
124
  def find_other_implementations(interface_name, current_tool_name)
125
- require_relative '../registry'
125
+ require_relative '../register'
126
126
 
127
127
  implementations = []
128
128
  interface_sym = interface_name.to_sym
129
129
 
130
130
  if config.debug
131
131
  say " [DEBUG] Looking for tools implementing '#{interface_name}' (excluding '#{current_tool_name}')", :dim
132
- say " [DEBUG] Registry tools: #{Registry.tools.inspect}", :dim
132
+ say " [DEBUG] Register tools: #{Register.tools.inspect}", :dim
133
133
  end
134
134
 
135
- Registry.tools.each do |tool_name|
135
+ Register.tools.each do |tool_name|
136
136
  next if tool_name == current_tool_name
137
137
 
138
138
  begin
139
- # Don't pass registry_path - let it use the default
140
- tool_metadata = Registry.load_tool_metadata(tool_name.to_sym)
139
+ # Don't pass register_path - let it use the default
140
+ tool_metadata = Register.load_tool_metadata(tool_name.to_sym)
141
141
  if config.debug
142
142
  say " [DEBUG] #{tool_name} -> metadata: #{tool_metadata ? tool_metadata.implements : 'nil'}", :dim
143
143
  end