rubycli 0.1.1

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,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rubycli
4
+ module CommandLine
5
+ USAGE = <<~USAGE
6
+ Usage: rubycli [--new|-n] [--pre-script SRC] [--json-args | --eval-args] TARGET_PATH [CLASS_OR_MODULE] [-- CLI_ARGS...]
7
+
8
+ Examples:
9
+ rubycli scripts/sample_runner.rb echo --message hello
10
+ rubycli scripts/sample_runner.rb AlternateRunner greet --name Ruby
11
+ rubycli --new lib/akiya_fetcher.rb fetch_simplified_html https://example.com
12
+
13
+ Options:
14
+ --new, -n Instantiate the class/module before invoking CLI commands
15
+ --pre-script SRC Evaluate Ruby code and use its result as the exposed target (--init alias)
16
+ --json-args Treat all following arguments as JSON
17
+ --eval-args Evaluate following arguments as Ruby code
18
+ (Note: --json-args and --eval-args are mutually exclusive)
19
+
20
+ When CLASS_OR_MODULE is omitted, Rubycli infers it from the file name in CamelCase.
21
+ Method return values are printed to STDOUT by default.
22
+ CLI_ARGS are forwarded to Rubycli unchanged.
23
+ USAGE
24
+
25
+ module_function
26
+
27
+ def run(argv = ARGV)
28
+ args = Array(argv).dup
29
+ Rubycli.environment.enable_print_result!
30
+
31
+ if args.empty?
32
+ $stdout.puts(USAGE)
33
+ return 1
34
+ end
35
+
36
+ new_flag = false
37
+ json_mode = false
38
+ eval_mode = false
39
+ pre_script_sources = []
40
+
41
+ loop do
42
+ arg = args.first
43
+ break unless arg
44
+
45
+ case arg
46
+ when '-h', '--help', 'help'
47
+ $stdout.puts(USAGE)
48
+ return 0
49
+ when '--new', '-n'
50
+ new_flag = true
51
+ args.shift
52
+ when /\A--pre-script=(.+)\z/, /\A--init=(.+)\z/
53
+ label = Regexp.last_match(0).start_with?('--pre-script') ? '--pre-script' : '--init'
54
+ expr = Regexp.last_match(1)
55
+ pre_script_sources << { value: expr, context: "(inline #{label})" }
56
+ args.shift
57
+ when '--pre-script', '--init'
58
+ flag = args.shift
59
+ src = args.shift
60
+ unless src
61
+ warn "#{flag} requires a file path or inline Ruby code"
62
+ return 1
63
+ end
64
+ context = File.file?(src) ? File.expand_path(src) : "(inline #{flag})"
65
+ pre_script_sources << { value: src, context: context }
66
+ when '--json-args'
67
+ json_mode = true
68
+ args.shift
69
+ when '--eval-args'
70
+ eval_mode = true
71
+ args.shift
72
+ when '--print-result'
73
+ args.shift
74
+ when '--'
75
+ args.shift
76
+ break
77
+ else
78
+ break
79
+ end
80
+ end
81
+
82
+ if args.empty?
83
+ $stdout.puts(USAGE)
84
+ return 1
85
+ end
86
+
87
+ target_path = args.shift
88
+ class_or_module = nil
89
+ possible_class = args.first
90
+ if possible_class && possible_class != '--' && possible_class.match?(/\A[A-Z]/)
91
+ class_or_module = args.shift
92
+ end
93
+ args.shift if args.first == '--'
94
+
95
+ if json_mode && eval_mode
96
+ warn '--json-args and --eval-args cannot be used at the same time'
97
+ return 1
98
+ end
99
+
100
+ Rubycli::Runner.execute(
101
+ target_path,
102
+ class_or_module,
103
+ args,
104
+ new: new_flag,
105
+ json: json_mode,
106
+ eval_args: eval_mode,
107
+ pre_scripts: pre_script_sources
108
+ )
109
+
110
+ 0
111
+ rescue Rubycli::Runner::PreScriptError => e
112
+ warn e.message
113
+ 1
114
+ end
115
+ end
116
+ end