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,153 @@
1
+ ---
2
+ layout: default
3
+ title: Interfaces
4
+ nav_order: 3
5
+ has_children: true
6
+ ---
7
+
8
+ = Interfaces
9
+
10
+ Ukiryu provides multiple ways to interact with tools, each suited for different use cases.
11
+
12
+ // Overview
13
+ == Overview
14
+
15
+ Ukiryu supports three primary interfaces:
16
+
17
+ * link:/interfaces/ruby-api[Ruby API] - Programmatic interface for Ruby applications
18
+ * link:/interfaces/cli[Command Line Interface] - Interactive shell usage
19
+ * link:/interfaces/configuration[Configuration] - Environment variables and settings
20
+
21
+ Each interface supports the same core functionality with appropriate trade-offs:
22
+
23
+ [cols="1,1,2"]
24
+ |===
25
+ |Interface |Best For |Key Features
26
+
27
+ |Ruby API |Applications, libraries |Type-safe parameters, structured results, error handling
28
+
29
+ |CLI |Scripts, automation |Simple syntax, shell integration, human-readable output
30
+
31
+ |ENV Variables |CI/CD, deployment |Global configuration, override settings
32
+ |===
33
+
34
+ // Configuration Across Interfaces
35
+ == Configuration Across Interfaces
36
+
37
+ All interfaces support the same configuration options with consistent precedence:
38
+
39
+ [NOTE]
40
+ .Configuration Precedence (Highest to Lowest)
41
+ 1. Environment variables (`UKIRYU_*`)
42
+ 2. Command-line parameters (`key=value`)
43
+ 3. Ruby API parameters (`{key: value}`)
44
+ 4. Profile defaults (from YAML)
45
+
46
+ === Example: Timeout Configuration
47
+
48
+ [source,ruby]
49
+ ----
50
+ // Ruby API - lowest precedence
51
+ result = tool.execute(:export, params, timeout: 60)
52
+ ----
53
+
54
+ [source,bash]
55
+ ----
56
+ # CLI - medium precedence
57
+ ukiryu exec inkscape export timeout=120 inputs=drawing.svg
58
+ ----
59
+
60
+ [source,bash]
61
+ ----
62
+ # ENV - highest precedence
63
+ export UKIRYU_TIMEOUT=180
64
+ ukiryu exec inkscape export inputs=drawing.svg
65
+ ----
66
+
67
+ Result: The command uses 180 second timeout (from ENV).
68
+
69
+ // Common Patterns
70
+ == Common Patterns
71
+
72
+ === Error Handling
73
+
74
+ [source,ruby]
75
+ ----
76
+ // Ruby API - structured exceptions
77
+ begin
78
+ result = tool.execute(:export, params)
79
+ rescue Ukiryu::ExecutionError => e
80
+ logger.error("Command failed: #{e.result.stderr}")
81
+ end
82
+ ----
83
+
84
+ [source,bash]
85
+ ----
86
+ # CLI - exit codes
87
+ ukiryu exec inkscape export inputs=drawing.svg
88
+ if [ $? -ne 0 ]; then
89
+ echo "Command failed"
90
+ fi
91
+ ----
92
+
93
+ === Result Inspection
94
+
95
+ [source,ruby]
96
+ ----
97
+ // Ruby API - rich result object
98
+ result = tool.execute(:export, params)
99
+ puts "Success: #{result.success?}"
100
+ puts "Duration: #{result.metadata.duration_seconds}s"
101
+ puts "Command: #{result.command_info.full_command}"
102
+ puts "Stdout: #{result.output.stdout}"
103
+ ----
104
+
105
+ === Tool Discovery
106
+
107
+ [source,ruby]
108
+ ----
109
+ // Ruby API
110
+ tool = Ukiryu::Tool.get(:inkscape)
111
+ puts tool.available? # Is tool installed?
112
+ puts tool.version # Detected version
113
+ puts tool.executable # Full path to executable
114
+ ----
115
+
116
+ [source,bash]
117
+ ----
118
+ # CLI
119
+ ukiryu info inkscape # Detailed tool information
120
+ ukiryu list # All available tools
121
+ ukiryu describe inkscape # Command documentation
122
+ ----
123
+
124
+ // Choosing the Right Interface
125
+ == Choosing the Right Interface
126
+
127
+ === Use Ruby API When
128
+
129
+ * Building Ruby applications
130
+ * Need programmatic error handling
131
+ * Want type-safe parameters
132
+ * Processing results in code
133
+
134
+ === Use CLI When
135
+
136
+ * Writing shell scripts
137
+ * Interactive tool usage
138
+ * Quick one-off commands
139
+ * Integrating with Unix pipelines
140
+
141
+ === Use ENV Variables When
142
+
143
+ * Configuring CI/CD pipelines
144
+ * Setting global defaults
145
+ * Overriding tool behavior without code changes
146
+ * Debugging with verbose output
147
+
148
+ // See Also
149
+ == See Also
150
+
151
+ * link:/features/configuration[Configuration Options] - All configuration methods
152
+ * link:/reference/configuration-options[Configuration Reference] - Complete option list
153
+ * link:/guides/[Guides] - Task-specific tutorials
@@ -0,0 +1,538 @@
1
+ ---
2
+ layout: default
3
+ title: Ruby API
4
+ parent: Interfaces
5
+ nav_order: 1
6
+ ---
7
+
8
+ == Ruby API
9
+
10
+ The Ruby API provides a programmatic interface for executing tools with type-safe parameters and structured results.
11
+
12
+ // Purpose
13
+ == Purpose
14
+
15
+ This page documents the Ruby API for executing commands, handling results, and managing configuration.
16
+
17
+ // References
18
+ == References
19
+
20
+ * `Ukiryu::Tool` - Main tool interface
21
+ * `Ukiryu::Register` - Tool profile register
22
+ * `Ukiryu::Execution::Result` - Result object
23
+ * link:/reference/ruby-api[API Reference]
24
+
25
+ // Concepts
26
+ == Concepts
27
+
28
+ * **Tool instance**: Cached object representing a specific tool
29
+ * **Command execution**: Type-safe parameter passing with validation
30
+ * **Result object**: Structured output with metadata
31
+ * **Error handling**: Exception-based error reporting
32
+ * **Configuration precedence**: ENV > parameters > defaults
33
+
34
+ // Basic Usage
35
+ == Basic Usage
36
+
37
+ === Getting a Tool
38
+
39
+ [source,ruby]
40
+ ----
41
+ require 'ukiryu'
42
+
43
+ # Get tool by name
44
+ tool = Ukiryu::Tool.get(:inkscape)
45
+
46
+ # Check availability
47
+ if tool.available?
48
+ puts "Inkscape is installed at: #{tool.executable}"
49
+ puts "Version: #{tool.version}"
50
+ else
51
+ puts "Inkscape is not installed"
52
+ end
53
+ ----
54
+
55
+ === Executing Commands
56
+
57
+ [source,ruby]
58
+ ----
59
+ # Execute a command with parameters
60
+ result = tool.execute(:export, {
61
+ inputs: ['drawing.svg'],
62
+ output: 'drawing.png',
63
+ format: :png
64
+ })
65
+
66
+ # Check success
67
+ if result.success?
68
+ puts "Conversion successful!"
69
+ else
70
+ puts "Conversion failed!"
71
+ puts "Error: #{result.stderr}"
72
+ end
73
+ ----
74
+
75
+ // Configuration Methods
76
+ == Configuration Methods
77
+
78
+ === Method 1: Ruby API Parameters (Lowest Precedence)
79
+
80
+ Pass parameters directly to `execute`:
81
+
82
+ [source,ruby]
83
+ ----
84
+ result = tool.execute(:export, {
85
+ inputs: ['drawing.svg'],
86
+ output: 'drawing.png',
87
+ format: :png,
88
+ dpi: 300,
89
+ width: 1024,
90
+ height: 768
91
+ }, timeout: 60) # Execution timeout in seconds
92
+ ----
93
+
94
+ === Method 2: Global Configuration (Medium Precedence)
95
+
96
+ Set default configuration for all operations:
97
+
98
+ [source,ruby]
99
+ ----
100
+ # Set register path
101
+ Ukiryu::Register.default_register_path = '/path/to/register'
102
+
103
+ # Set default timeout
104
+ Ukiryu::Executor::DEFAULT_TIMEOUT = 120
105
+ ----
106
+
107
+ === Method 3: Environment Variables (Highest Precedence)
108
+
109
+ Set environment variables to override all other configuration:
110
+
111
+ [source,ruby]
112
+ ----
113
+ # Set before loading Ukiryu
114
+ ENV['UKIRYU_REGISTER'] = '/path/to/register'
115
+ ENV['UKIRYU_TIMEOUT'] = '180'
116
+ ENV['UKIRYU_DEBUG'] = 'true'
117
+
118
+ require 'ukiryu'
119
+
120
+ tool = Ukiryu::Tool.get(:inkscape)
121
+ result = tool.execute(:export, params)
122
+ # Uses 180 second timeout from ENV
123
+ ----
124
+
125
+ === Configuration Precedence Example
126
+
127
+ [source,ruby]
128
+ ----
129
+ # Profile default: 90 seconds
130
+ # Ruby API parameter: 60 seconds
131
+ # ENV variable: 180 seconds (wins!)
132
+
133
+ ENV['UKIRYU_TIMEOUT'] = '180'
134
+ tool = Ukiryu::Tool.get(:inkscape)
135
+
136
+ result = tool.execute(:export, {
137
+ inputs: ['drawing.svg'],
138
+ output: 'drawing.png'
139
+ }, timeout: 60)
140
+
141
+ # Result: Uses 180 second timeout from ENV
142
+ ----
143
+
144
+ // Result Object
145
+ == Result Object
146
+
147
+ The `execute` method returns a structured result object:
148
+
149
+ [source,ruby]
150
+ ----
151
+ result = tool.execute(:export, params)
152
+
153
+ # Command information
154
+ puts "Executable: #{result.command_info.executable}"
155
+ puts "Arguments: #{result.command_info.arguments}"
156
+ puts "Full command: #{result.command_info.full_command}"
157
+ puts "Shell: #{result.command_info.shell}"
158
+
159
+ # Output
160
+ puts "Exit status: #{result.output.exit_status}"
161
+ puts "Stdout: #{result.output.stdout}"
162
+ puts "Stderr: #{result.output.stderr}"
163
+ puts "Success: #{result.success?}"
164
+
165
+ # Metadata
166
+ puts "Duration: #{result.metadata.duration_seconds}s"
167
+ puts "Formatted: #{result.metadata.formatted_duration}"
168
+ puts "Started: #{result.metadata.started_at}"
169
+ puts "Finished: #{result.metadata.finished_at}"
170
+ ----
171
+
172
+ === Convenience Methods
173
+
174
+ [source,ruby]
175
+ ----
176
+ result = tool.execute(:export, params)
177
+
178
+ # Check success
179
+ result.success? # => true if exit status == 0
180
+ result.failure? # => true if exit status != 0
181
+
182
+ # Access output
183
+ result.stdout # => Stdout (stripped)
184
+ result.stderr # => Stderr (stripped)
185
+ result.stdout_lines # => Array of lines
186
+ result.stderr_lines # => Array of lines
187
+ ----
188
+
189
+ // Type System
190
+ == Type System
191
+
192
+ Ukiryu validates parameter types against the profile definition.
193
+
194
+ === Supported Types
195
+
196
+ [source,ruby]
197
+ ----
198
+ # file - File path with platform formatting
199
+ tool.execute(:export, {
200
+ inputs: ['drawing.svg'], # Array of file paths
201
+ output: 'output.png' # Single file path
202
+ })
203
+
204
+ # string - Text value
205
+ tool.execute(:convert, {
206
+ text: 'Hello World'
207
+ })
208
+
209
+ # integer - Whole number with range
210
+ tool.execute(:export, {
211
+ dpi: 300 # Within 1-10000 range
212
+ })
213
+
214
+ # float - Decimal number with range
215
+ tool.execute(:export, {
216
+ background_opacity: 0.5 # Within 0.0-1.0 range
217
+ })
218
+
219
+ # symbol - Enumerated value
220
+ tool.execute(:export, {
221
+ format: :png # Must be in values list
222
+ })
223
+
224
+ # boolean - True/false flag
225
+ tool.execute(:export, {
226
+ plain: true,
227
+ batch_process: true
228
+ })
229
+
230
+ # array - Multiple values
231
+ tool.execute(:export, {
232
+ export_ids: ['id1', 'id2', 'id3'] # Joined with separator
233
+ })
234
+ ----
235
+
236
+ === Type Validation Errors
237
+
238
+ [source,ruby]
239
+ ----
240
+ # Invalid type raises error
241
+ begin
242
+ tool.execute(:export, {
243
+ format: :unsupported # Not in values list
244
+ })
245
+ rescue Ukiryu::TypeError => e
246
+ puts "Type error: #{e.message}"
247
+ # => "Invalid value :unsupported for format. Valid values: svg, png, pdf, ..."
248
+ end
249
+
250
+ # Out of range raises error
251
+ begin
252
+ tool.execute(:export, {
253
+ dpi: -5 # Outside range 1-10000
254
+ })
255
+ rescue Ukiryu::RangeError => e
256
+ puts "Range error: #{e.message}"
257
+ # => "Value -5 is outside valid range 1-10000 for dpi"
258
+ end
259
+ ----
260
+
261
+ // Error Handling
262
+ == Error Handling
263
+
264
+ === Exception Types
265
+
266
+ [source,ruby]
267
+ ----
268
+ require 'ukiryu'
269
+
270
+ begin
271
+ tool = Ukiryu::Tool.get(:inkscape)
272
+ result = tool.execute(:export, params)
273
+
274
+ rescue Ukiryu::ToolNotFoundError => e
275
+ # Tool not in register
276
+ puts "Tool not found!"
277
+ puts "Available tools: #{Ukiryu::Register.tools.join(', ')}"
278
+
279
+ rescue Ukiryu::ProfileNotFoundError => e
280
+ # No compatible profile for platform/shell
281
+ puts "No profile available for this platform/shell"
282
+
283
+ rescue Ukiryu::ExecutionError => e
284
+ # Command failed (non-zero exit)
285
+ puts "Command failed!"
286
+ puts "Exit code: #{e.result.exit_status}"
287
+ puts "Command: #{e.result.command}"
288
+ puts "Stderr: #{e.result.stderr}"
289
+
290
+ rescue Ukiryu::TimeoutError => e
291
+ # Command exceeded timeout
292
+ puts "Command timed out after #{e.timeout} seconds"
293
+ end
294
+ ----
295
+
296
+ === Handling Failures Gracefully
297
+
298
+ [source,ruby]
299
+ ----
300
+ # Allow failure without exception
301
+ result = tool.execute(:export, params, allow_failure: true)
302
+
303
+ if result.failure?
304
+ # Handle failure gracefully
305
+ logger.warn("Export failed: #{result.stderr}")
306
+ # Continue processing...
307
+ end
308
+ ----
309
+
310
+ === Detailed Error Information
311
+
312
+ [source,ruby]
313
+ ----
314
+ begin
315
+ result = tool.execute(:export, params)
316
+ rescue Ukiryu::ExecutionError => e
317
+ # Access full result information
318
+ result = e.result
319
+
320
+ puts "Executable: #{result.command_info.executable}"
321
+ puts "Command: #{result.command_info.full_command}"
322
+ puts "Exit status: #{result.exit_status}"
323
+ puts "Stdout: #{result.stdout}"
324
+ puts "Stderr: #{result.stderr}"
325
+
326
+ # Log error details
327
+ logger.error("Command failed", {
328
+ executable: result.command_info.executable,
329
+ command: result.command_info.full_command,
330
+ exit_status: result.exit_status,
331
+ stderr: result.stderr
332
+ })
333
+ end
334
+ ----
335
+
336
+ // Advanced Usage
337
+ == Advanced Usage
338
+
339
+ === Tool Caching
340
+
341
+ [source,ruby]
342
+ ----
343
+ # Tool instances are cached by {name}-{platform}-{shell}-{version}
344
+ tool1 = Ukiryu::Tool.get(:inkscape)
345
+ tool2 = Ukiryu::Tool.get(:inkscape)
346
+
347
+ tool1.equal?(tool2) # => true (same cached instance)
348
+
349
+ # Clear cache and reload
350
+ Ukiryu::Tool.clear_cache
351
+ tool3 = Ukiryu::Tool.get(:inkscape, reload: true)
352
+ ----
353
+
354
+ === Version Selection
355
+
356
+ [source,ruby]
357
+ ----
358
+ # Get specific version
359
+ tool = Ukiryu::Tool.get(:inkscape, version: '0.92')
360
+
361
+ # Auto-detect version
362
+ tool = Ukiryu::Tool.get(:inkscape)
363
+ # Uses version detection from profile
364
+ # Matches highest compatible profile
365
+
366
+ # Get version info
367
+ puts "Profile version: #{tool.profile.version}"
368
+ puts "Detected version: #{tool.version}"
369
+ ----
370
+
371
+ === Platform/Shell Override
372
+
373
+ [source,ruby]
374
+ ----
375
+ # Auto-detect platform and shell
376
+ tool = Ukiryu::Tool.get(:inkscape)
377
+
378
+ # Force specific platform
379
+ tool = Ukiryu::Tool.get(:inkscape, platform: :linux)
380
+
381
+ # Force specific shell
382
+ tool = Ukiryu::Tool.get(:inkscape, shell: :zsh)
383
+ ----
384
+
385
+ === Working Directory
386
+
387
+ [source,ruby]
388
+ ----
389
+ # Execute in specific directory
390
+ result = tool.execute(:export, params, cwd: '/path/to/directory')
391
+ ----
392
+
393
+ === Stdin Input
394
+
395
+ [source,ruby]
396
+ ----
397
+ # Pass stdin data to command
398
+ result = tool.execute(:compress, {
399
+ inputs: ['-'] # Read from stdin
400
+ }, stdin: "Hello World\n")
401
+
402
+ # Or pass IO object
403
+ File.open('data.txt') do |file|
404
+ result = tool.execute(:compress, {
405
+ inputs: ['-']
406
+ }, stdin: file)
407
+ end
408
+ ----
409
+
410
+ // Examples
411
+ == Examples
412
+
413
+ === Image Conversion with ImageMagick
414
+
415
+ [source,ruby]
416
+ ----
417
+ require 'ukiryu'
418
+
419
+ tool = Ukiryu::Tool.get(:imagemagick)
420
+
421
+ # Convert to different format
422
+ result = tool.execute(:convert, {
423
+ inputs: ['photo.jpg'],
424
+ output: 'photo.png'
425
+ })
426
+
427
+ # With options
428
+ result = tool.execute(:convert, {
429
+ inputs: ['photo.jpg'],
430
+ output: 'photo.png',
431
+ resize: '50%',
432
+ quality: 85,
433
+ strip: true # Remove metadata
434
+ })
435
+
436
+ if result.success?
437
+ puts "Conversion successful!"
438
+ puts "Output size: #{File.size('photo.png')} bytes"
439
+ end
440
+ ----
441
+
442
+ === PDF Processing with Ghostscript
443
+
444
+ [source,ruby]
445
+ ----
446
+ require 'ukiryu'
447
+
448
+ tool = Ukiryu::Tool.get(:ghostscript)
449
+
450
+ # Compress PDF
451
+ result = tool.execute(:convert, {
452
+ inputs: ['document.pdf'],
453
+ device: :pdfwrite,
454
+ output: 'document-compressed.pdf',
455
+ safer: true,
456
+ quiet: true
457
+ })
458
+
459
+ # Extract pages as images
460
+ result = tool.execute(:convert, {
461
+ inputs: ['presentation.pdf'],
462
+ device: :png16m,
463
+ output: 'slide-%03d.png',
464
+ quiet: true
465
+ })
466
+ ----
467
+
468
+ === Batch Processing
469
+
470
+ [source,ruby]
471
+ ----
472
+ require 'ukiryu'
473
+
474
+ tool = Ukiryu::Tool.get(:inkscape)
475
+
476
+ # Process multiple files
477
+ files = Dir['*.svg']
478
+ files.each do |input_file|
479
+ output_file = input_file.sub('.svg', '.png')
480
+
481
+ result = tool.execute(:export, {
482
+ inputs: [input_file],
483
+ output: output_file,
484
+ format: :png,
485
+ dpi: 300
486
+ })
487
+
488
+ if result.failure?
489
+ puts "Failed to convert #{input_file}: #{result.stderr}"
490
+ else
491
+ puts "Converted #{input_file} -> #{output_file}"
492
+ end
493
+ end
494
+ ----
495
+
496
+ === Custom Error Handling
497
+
498
+ [source,ruby]
499
+ ----
500
+ require 'ukiryu'
501
+
502
+ class ConversionService
503
+ def initialize(tool_name)
504
+ @tool = Ukiryu::Tool.get(tool_name)
505
+ end
506
+
507
+ def convert(input, output, options = {})
508
+ result = @tool.execute(:export, {
509
+ inputs: [input],
510
+ output: output
511
+ }.merge(options))
512
+
513
+ unless result.success?
514
+ raise ConversionError, "Failed to convert #{input} to #{output}: #{result.stderr}"
515
+ end
516
+
517
+ result
518
+ end
519
+
520
+ class ConversionError < StandardError; end
521
+ end
522
+
523
+ # Usage
524
+ service = ConversionService.new(:inkscape)
525
+ begin
526
+ service.convert('drawing.svg', 'drawing.png', format: :png)
527
+ rescue ConversionService::ConversionError => e
528
+ puts e.message
529
+ end
530
+ ----
531
+
532
+ // See Also
533
+ == See Also
534
+
535
+ * link:/interfaces/cli[Command Line Interface] - Shell-based tool usage
536
+ * link:/features/configuration[Configuration Options] - All configuration methods
537
+ * link:/guides/[Guides] - Task-specific tutorials
538
+ * link:/reference/ruby-api[API Reference] - Complete API documentation