• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

type-ruby / t-ruby / 20215351018

14 Dec 2025 10:49PM UTC coverage: 74.211% (-0.03%) from 74.239%
20215351018

push

github

yhk1038
feat(cli): add version check and update commands

- Add `trc -v` to check for new versions from RubyGems.org
- Add `trc update` command to update t-ruby to latest version
- Create VersionChecker class for API communication

32 of 44 new or added lines in 3 files covered. (72.73%)

1 existing line in 1 file now uncovered.

4446 of 5991 relevant lines covered (74.21%)

1008.2 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.73
/lib/t_ruby/cli.rb
1
# frozen_string_literal: true
2

3
module TRuby
1✔
4
  class CLI
1✔
5
    HELP_TEXT = <<~HELP.freeze
1✔
6
      t-ruby compiler (trc) v#{VERSION}
7

8
      Usage:
9
        trc <file.trb>           Compile a .trb file to .rb
10
        trc <file.rb>            Copy .rb file to build/ and generate .rbs
11
        trc --init               Initialize a new t-ruby project
12
        trc --config, -c <path>  Use custom config file
13
        trc --watch, -w          Watch input files and recompile on change
14
        trc --decl <file.trb>    Generate .d.trb declaration file
15
        trc --lsp                Start LSP server (for IDE integration)
16
        trc update               Update t-ruby to the latest version
17
        trc --version, -v        Show version (and check for updates)
18
        trc --help, -h           Show this help
19

20
      Examples:
21
        trc hello.trb            Compile hello.trb to build/hello.rb
22
        trc utils.rb             Copy utils.rb to build/ and generate utils.rbs
23
        trc --init               Create trbconfig.yml and src/, build/ directories
24
        trc -c custom.yml file.trb  Compile with custom config file
25
        trc -w                   Watch all .trb and .rb files in current directory
26
        trc -w src/              Watch all .trb and .rb files in src/ directory
27
        trc --watch hello.trb    Watch specific file for changes
28
        trc --decl hello.trb     Generate hello.d.trb declaration file
29
        trc --lsp                Start language server for VS Code
30
    HELP
31

32
    def self.run(args)
1✔
33
      new(args).run
11✔
34
    end
35

36
    def initialize(args)
1✔
37
      @args = args
32✔
38
    end
39

40
    def run
1✔
41
      if @args.empty? || @args.include?("--help") || @args.include?("-h")
28✔
42
        puts HELP_TEXT
5✔
43
        return
5✔
44
      end
45

46
      if @args.include?("--version") || @args.include?("-v")
23✔
47
        puts "trc #{VERSION}"
4✔
48
        check_for_updates
4✔
49
        return
4✔
50
      end
51

52
      if @args.include?("update")
19✔
NEW
53
        update_gem
×
UNCOV
54
        return
×
55
      end
56

57
      if @args.include?("--init")
19✔
58
        init_project
8✔
59
        return
8✔
60
      end
61

62
      if @args.include?("--lsp")
11✔
63
        start_lsp_server
×
64
        return
×
65
      end
66

67
      if @args.include?("--watch") || @args.include?("-w")
11✔
68
        start_watch_mode
×
69
        return
×
70
      end
71

72
      if @args.include?("--decl")
11✔
73
        input_file = @args[@args.index("--decl") + 1]
×
74
        generate_declaration(input_file)
×
75
        return
×
76
      end
77

78
      # Extract config path if --config or -c flag is present
79
      config_path = extract_config_path
11✔
80

81
      # Get input file (first non-flag argument)
82
      input_file = find_input_file
11✔
83
      compile(input_file, config_path: config_path)
11✔
84
    end
85

86
    private
1✔
87

88
    def check_for_updates
1✔
89
      result = VersionChecker.check
4✔
90
      return unless result
4✔
91

NEW
92
      puts ""
×
NEW
93
      puts "New version available: #{result[:latest]} (current: #{result[:current]})"
×
NEW
94
      puts "Run 'trc update' to update"
×
95
    end
96

97
    def update_gem
1✔
NEW
98
      puts "Updating t-ruby..."
×
NEW
99
      if VersionChecker.update
×
NEW
100
        puts "Successfully updated t-ruby!"
×
101
      else
NEW
102
        puts "Update failed. Try: gem install t-ruby"
×
103
      end
104
    end
105

106
    def init_project
1✔
107
      config_file = "trbconfig.yml"
8✔
108
      src_dir = "src"
8✔
109
      build_dir = "build"
8✔
110

111
      created = []
8✔
112
      skipped = []
8✔
113

114
      # Create trbconfig.yml with new schema
115
      if File.exist?(config_file)
8✔
116
        skipped << config_file
3✔
117
      else
118
        File.write(config_file, <<~YAML)
5✔
119
          # T-Ruby configuration file
120
          # See: https://type-ruby.github.io/docs/getting-started/project-configuration
121

122
          source:
123
            include:
124
              - #{src_dir}
125
            exclude: []
126
            extensions:
127
              - ".trb"
128
              - ".rb"
129

130
          output:
131
            ruby_dir: #{build_dir}
132
            # rbs_dir: sig  # Optional: separate directory for .rbs files
133
            # clean_before_build: false
134

135
          compiler:
136
            strictness: standard  # strict | standard | permissive
137
            generate_rbs: true
138
            target_ruby: "3.0"
139
            # experimental: []
140
            # checks:
141
            #   no_implicit_any: false
142
            #   no_unused_vars: false
143
            #   strict_nil: false
144

145
          watch:
146
            # paths: []  # Additional paths to watch
147
            debounce: 100
148
            # clear_screen: false
149
            # on_success: "bundle exec rspec"
150
        YAML
151
        created << config_file
5✔
152
      end
153

154
      # Create src/ directory
155
      if Dir.exist?(src_dir)
8✔
156
        skipped << "#{src_dir}/"
3✔
157
      else
158
        Dir.mkdir(src_dir)
5✔
159
        created << "#{src_dir}/"
5✔
160
      end
161

162
      # Create build/ directory
163
      if Dir.exist?(build_dir)
8✔
164
        skipped << "#{build_dir}/"
3✔
165
      else
166
        Dir.mkdir(build_dir)
5✔
167
        created << "#{build_dir}/"
5✔
168
      end
169

170
      # Output results
171
      if created.any?
8✔
172
        puts "Created: #{created.join(", ")}"
6✔
173
      end
174
      if skipped.any?
8✔
175
        puts "Skipped (already exists): #{skipped.join(", ")}"
4✔
176
      end
177
      if created.empty? && skipped.any?
8✔
178
        puts "Project already initialized."
2✔
179
      else
180
        puts "t-ruby project initialized successfully!"
6✔
181
      end
182
    end
183

184
    def start_lsp_server
1✔
185
      server = LSPServer.new
×
186
      server.run
×
187
    end
188

189
    def start_watch_mode
1✔
190
      # Get paths to watch (everything after --watch or -w flag)
191
      watch_index = @args.index("--watch") || @args.index("-w")
×
192
      paths = @args[(watch_index + 1)..]
×
193

194
      # Default to current directory if no paths specified
195
      paths = ["."] if paths.empty?
×
196

197
      config = Config.new
×
198
      watcher = Watcher.new(paths: paths, config: config)
×
199
      watcher.watch
×
200
    end
201

202
    def generate_declaration(input_file)
1✔
203
      config = Config.new
×
204
      generator = DeclarationGenerator.new
×
205

206
      output_path = generator.generate_file(input_file, config.out_dir)
×
207
      puts "Generated: #{input_file} -> #{output_path}"
×
208
    rescue ArgumentError => e
209
      puts "Error: #{e.message}"
×
210
      exit 1
×
211
    end
212

213
    def compile(input_file, config_path: nil)
1✔
214
      config = Config.new(config_path)
11✔
215
      compiler = Compiler.new(config)
11✔
216

217
      output_path = compiler.compile(input_file)
11✔
218
      puts "Compiled: #{input_file} -> #{output_path}"
6✔
219
    rescue ArgumentError => e
220
      puts "Error: #{e.message}"
5✔
221
      exit 1
5✔
222
    end
223

224
    # Extract config path from --config or -c flag
225
    def extract_config_path
1✔
226
      config_index = @args.index("--config") || @args.index("-c")
11✔
227
      return nil unless config_index
11✔
228

229
      @args[config_index + 1]
2✔
230
    end
231

232
    # Find the input file (first non-flag argument)
233
    def find_input_file
1✔
234
      skip_next = false
11✔
235
      @args.each do |arg|
11✔
236
        if skip_next
15✔
237
          skip_next = false
2✔
238
          next
2✔
239
        end
240

241
        # Skip known flags with arguments
242
        if %w[--config -c --decl].include?(arg)
13✔
243
          skip_next = true
2✔
244
          next
2✔
245
        end
246

247
        # Skip flags without arguments
248
        next if arg.start_with?("-")
11✔
249

250
        return arg
11✔
251
      end
252
      nil
253
    end
254
  end
255
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc