gorails 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -1
  3. data/Gemfile.lock +1 -1
  4. data/bin/update-deps +95 -0
  5. data/exe/gorails +3 -2
  6. data/lib/gorails/commands/railsbytes.rb +10 -10
  7. data/lib/gorails/commands.rb +1 -4
  8. data/lib/gorails/version.rb +1 -1
  9. data/lib/gorails.rb +11 -20
  10. data/vendor/deps/cli-kit/REVISION +1 -0
  11. data/vendor/deps/cli-kit/lib/cli/kit/args/definition.rb +301 -0
  12. data/vendor/deps/cli-kit/lib/cli/kit/args/evaluation.rb +237 -0
  13. data/vendor/deps/cli-kit/lib/cli/kit/args/parser/node.rb +131 -0
  14. data/vendor/deps/cli-kit/lib/cli/kit/args/parser.rb +128 -0
  15. data/vendor/deps/cli-kit/lib/cli/kit/args/tokenizer.rb +132 -0
  16. data/vendor/deps/cli-kit/lib/cli/kit/args.rb +15 -0
  17. data/vendor/deps/cli-kit/lib/cli/kit/base_command.rb +29 -0
  18. data/vendor/deps/cli-kit/lib/cli/kit/command_help.rb +256 -0
  19. data/vendor/deps/cli-kit/lib/cli/kit/command_registry.rb +141 -0
  20. data/vendor/deps/cli-kit/lib/cli/kit/config.rb +137 -0
  21. data/vendor/deps/cli-kit/lib/cli/kit/core_ext.rb +30 -0
  22. data/vendor/deps/cli-kit/lib/cli/kit/error_handler.rb +165 -0
  23. data/vendor/deps/cli-kit/lib/cli/kit/executor.rb +99 -0
  24. data/vendor/deps/cli-kit/lib/cli/kit/ini.rb +94 -0
  25. data/vendor/deps/cli-kit/lib/cli/kit/levenshtein.rb +89 -0
  26. data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +95 -0
  27. data/vendor/deps/cli-kit/lib/cli/kit/opts.rb +284 -0
  28. data/vendor/deps/cli-kit/lib/cli/kit/resolver.rb +67 -0
  29. data/vendor/deps/cli-kit/lib/cli/kit/sorbet_runtime_stub.rb +142 -0
  30. data/vendor/deps/cli-kit/lib/cli/kit/support/test_helper.rb +253 -0
  31. data/vendor/deps/cli-kit/lib/cli/kit/support.rb +10 -0
  32. data/vendor/deps/cli-kit/lib/cli/kit/system.rb +350 -0
  33. data/vendor/deps/cli-kit/lib/cli/kit/util.rb +133 -0
  34. data/vendor/deps/cli-kit/lib/cli/kit/version.rb +7 -0
  35. data/vendor/deps/cli-kit/lib/cli/kit.rb +151 -0
  36. data/vendor/deps/cli-ui/REVISION +1 -0
  37. data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +180 -0
  38. data/vendor/deps/cli-ui/lib/cli/ui/color.rb +98 -0
  39. data/vendor/deps/cli-ui/lib/cli/ui/formatter.rb +216 -0
  40. data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_stack.rb +116 -0
  41. data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style/box.rb +176 -0
  42. data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style/bracket.rb +149 -0
  43. data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style.rb +112 -0
  44. data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +300 -0
  45. data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +92 -0
  46. data/vendor/deps/cli-ui/lib/cli/ui/os.rb +58 -0
  47. data/vendor/deps/cli-ui/lib/cli/ui/printer.rb +72 -0
  48. data/vendor/deps/cli-ui/lib/cli/ui/progress.rb +102 -0
  49. data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +534 -0
  50. data/vendor/deps/cli-ui/lib/cli/ui/prompt/options_handler.rb +36 -0
  51. data/vendor/deps/cli-ui/lib/cli/ui/prompt.rb +354 -0
  52. data/vendor/deps/cli-ui/lib/cli/ui/sorbet_runtime_stub.rb +143 -0
  53. data/vendor/deps/cli-ui/lib/cli/ui/spinner/async.rb +46 -0
  54. data/vendor/deps/cli-ui/lib/cli/ui/spinner/spin_group.rb +292 -0
  55. data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +82 -0
  56. data/vendor/deps/cli-ui/lib/cli/ui/stdout_router.rb +264 -0
  57. data/vendor/deps/cli-ui/lib/cli/ui/terminal.rb +53 -0
  58. data/vendor/deps/cli-ui/lib/cli/ui/truncater.rb +107 -0
  59. data/vendor/deps/cli-ui/lib/cli/ui/version.rb +6 -0
  60. data/vendor/deps/cli-ui/lib/cli/ui/widgets/base.rb +37 -0
  61. data/vendor/deps/cli-ui/lib/cli/ui/widgets/status.rb +75 -0
  62. data/vendor/deps/cli-ui/lib/cli/ui/widgets.rb +91 -0
  63. data/vendor/deps/cli-ui/lib/cli/ui/wrap.rb +63 -0
  64. data/vendor/deps/cli-ui/lib/cli/ui.rb +356 -0
  65. metadata +57 -1
@@ -0,0 +1,107 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ require 'cli/ui'
5
+
6
+ module CLI
7
+ module UI
8
+ # Truncater truncates a string to a provided printable width.
9
+ module Truncater
10
+ PARSE_ROOT = :root
11
+ PARSE_ANSI = :ansi
12
+ PARSE_ESC = :esc
13
+ PARSE_ZWJ = :zwj
14
+
15
+ ESC = 0x1b
16
+ LEFT_SQUARE_BRACKET = 0x5b
17
+ ZWJ = 0x200d # emojipedia.org/emoji-zwj-sequences
18
+ SEMICOLON = 0x3b
19
+
20
+ # EMOJI_RANGE in particular is super inaccurate. This is best-effort.
21
+ # If you need this to be more accurate, we'll almost certainly accept a
22
+ # PR improving it.
23
+ EMOJI_RANGE = 0x1f300..0x1f5ff
24
+ NUMERIC_RANGE = 0x30..0x39
25
+ LC_ALPHA_RANGE = 0x40..0x5a
26
+ UC_ALPHA_RANGE = 0x60..0x71
27
+
28
+ TRUNCATED = "\x1b[0m…"
29
+
30
+ class << self
31
+ extend T::Sig
32
+
33
+ sig { params(text: String, printing_width: Integer).returns(String) }
34
+ def call(text, printing_width)
35
+ return text if text.size <= printing_width
36
+
37
+ width = 0
38
+ mode = PARSE_ROOT
39
+ truncation_index = T.let(nil, T.nilable(Integer))
40
+
41
+ codepoints = text.codepoints
42
+ codepoints.each.with_index do |cp, index|
43
+ case mode
44
+ when PARSE_ROOT
45
+ case cp
46
+ when ESC # non-printable, followed by some more non-printables.
47
+ mode = PARSE_ESC
48
+ when ZWJ # non-printable, followed by another non-printable.
49
+ mode = PARSE_ZWJ
50
+ else
51
+ width += width(cp)
52
+ if width >= printing_width
53
+ truncation_index ||= index
54
+ # it looks like we could break here but we still want the
55
+ # width calculation for the rest of the characters.
56
+ end
57
+ end
58
+ when PARSE_ESC
59
+ mode = case cp
60
+ when LEFT_SQUARE_BRACKET
61
+ PARSE_ANSI
62
+ else
63
+ PARSE_ROOT
64
+ end
65
+ when PARSE_ANSI
66
+ # ANSI escape codes preeeetty much have the format of:
67
+ # \x1b[0-9;]+[A-Za-z]
68
+ case cp
69
+ when NUMERIC_RANGE, SEMICOLON
70
+ when LC_ALPHA_RANGE, UC_ALPHA_RANGE
71
+ mode = PARSE_ROOT
72
+ else
73
+ # unexpected. let's just go back to the root state I guess?
74
+ mode = PARSE_ROOT
75
+ end
76
+ when PARSE_ZWJ
77
+ # consume any character and consider it as having no width
78
+ # width(x+ZWJ+y) = width(x).
79
+ mode = PARSE_ROOT
80
+ end
81
+ end
82
+
83
+ # Without the `width <= printing_width` check, we truncate
84
+ # "foo\x1b[0m" for a width of 3, but it should not be truncated.
85
+ # It's specifically for the case where we decided "Yes, this is the
86
+ # point at which we'd have to add a truncation!" but it's actually
87
+ # the end of the string.
88
+ return text if !truncation_index || width <= printing_width
89
+
90
+ T.must(codepoints[0...truncation_index]).pack('U*') + TRUNCATED
91
+ end
92
+
93
+ private
94
+
95
+ sig { params(printable_codepoint: Integer).returns(Integer) }
96
+ def width(printable_codepoint)
97
+ case printable_codepoint
98
+ when EMOJI_RANGE
99
+ 2
100
+ else
101
+ 1
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,6 @@
1
+ # typed: true
2
+ module CLI
3
+ module UI
4
+ VERSION = '1.5.1'
5
+ end
6
+ end
@@ -0,0 +1,37 @@
1
+ # typed: true
2
+ require('cli/ui')
3
+
4
+ module CLI
5
+ module UI
6
+ module Widgets
7
+ class Base
8
+ extend T::Sig
9
+ extend T::Helpers
10
+ abstract!
11
+
12
+ sig { params(argstring: String).returns(String) }
13
+ def self.call(argstring)
14
+ new(argstring).render
15
+ end
16
+
17
+ sig { params(argstring: String).void }
18
+ def initialize(argstring)
19
+ pat = self.class.argparse_pattern
20
+ unless (@match_data = pat.match(argstring))
21
+ raise(Widgets::InvalidWidgetArguments.new(argstring, pat))
22
+ end
23
+
24
+ @match_data.names.each do |name|
25
+ instance_variable_set(:"@#{name}", @match_data[name])
26
+ end
27
+ end
28
+
29
+ sig { abstract.returns(Regexp) }
30
+ def self.argparse_pattern; end
31
+
32
+ sig { abstract.returns(String) }
33
+ def render; end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,75 @@
1
+ # typed: true
2
+ # frozen-string-literal: true
3
+
4
+ require('cli/ui')
5
+
6
+ module CLI
7
+ module UI
8
+ module Widgets
9
+ class Status < Widgets::Base
10
+ ARGPARSE_PATTERN = %r{
11
+ \A (?<succeeded> \d+)
12
+ : (?<failed> \d+)
13
+ : (?<working> \d+)
14
+ : (?<pending> \d+) \z
15
+ }x # e.g. "1:23:3:404"
16
+ OPEN = Color::RESET.code + Color::BOLD.code + '[' + Color::RESET.code
17
+ CLOSE = Color::RESET.code + Color::BOLD.code + ']' + Color::RESET.code
18
+ ARROW = Color::RESET.code + Color::GRAY.code + '◂' + Color::RESET.code
19
+ COMMA = Color::RESET.code + Color::GRAY.code + ',' + Color::RESET.code
20
+
21
+ SPINNER_STOPPED = '⠿'
22
+ EMPTY_SET = '∅'
23
+
24
+ sig { override.returns(Regexp) }
25
+ def self.argparse_pattern
26
+ ARGPARSE_PATTERN
27
+ end
28
+
29
+ sig { override.returns(String) }
30
+ def render
31
+ if zero?(@succeeded) && zero?(@failed) && zero?(@working) && zero?(@pending)
32
+ Color::RESET.code + Color::BOLD.code + EMPTY_SET + Color::RESET.code
33
+ else
34
+ # [ 0✓ , 2✗ ◂ 3⠼ ◂ 4⌛︎ ]
35
+ "#{OPEN}#{succeeded_part}#{COMMA}#{failed_part}#{ARROW}#{working_part}#{ARROW}#{pending_part}#{CLOSE}"
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ sig { params(num_str: String).returns(T::Boolean) }
42
+ def zero?(num_str)
43
+ num_str == '0'
44
+ end
45
+
46
+ sig { params(num_str: String, rune: String, color: Color).returns(String) }
47
+ def colorize_if_nonzero(num_str, rune, color)
48
+ color = Color::GRAY if zero?(num_str)
49
+ color.code + num_str + rune
50
+ end
51
+
52
+ sig { returns(String) }
53
+ def succeeded_part
54
+ colorize_if_nonzero(@succeeded, Glyph::CHECK.char, Color::GREEN)
55
+ end
56
+
57
+ sig { returns(String) }
58
+ def failed_part
59
+ colorize_if_nonzero(@failed, Glyph::X.char, Color::RED)
60
+ end
61
+
62
+ sig { returns(String) }
63
+ def working_part
64
+ rune = zero?(@working) ? SPINNER_STOPPED : Spinner.current_rune
65
+ colorize_if_nonzero(@working, rune, Color::BLUE)
66
+ end
67
+
68
+ sig { returns(String) }
69
+ def pending_part
70
+ colorize_if_nonzero(@pending, Glyph::HOURGLASS.char, Color::WHITE)
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,91 @@
1
+ # typed: true
2
+ require('cli/ui')
3
+
4
+ module CLI
5
+ module UI
6
+ # Widgets are formatter objects with more custom implementations than the
7
+ # other features, which all center around formatting text with colours,
8
+ # etc.
9
+ #
10
+ # If you want to extend CLI::UI with your own widgets, you may want to do
11
+ # something like this:
12
+ #
13
+ # require('cli/ui')
14
+ # class MyWidget < CLI::UI::Widgets::Base
15
+ # # ...
16
+ # end
17
+ # CLI::UI::Widgets.register('my-widget') { MyWidget }
18
+ # puts(CLI::UI.fmt("{{@widget/my-widget:args}}"))
19
+ module Widgets
20
+ extend T::Sig
21
+
22
+ MAP = {}
23
+
24
+ autoload(:Base, 'cli/ui/widgets/base')
25
+
26
+ sig { params(name: String, cb: T.proc.returns(T.class_of(Widgets::Base))).void }
27
+ def self.register(name, &cb)
28
+ MAP[name] = cb
29
+ end
30
+
31
+ autoload(:Status, 'cli/ui/widgets/status')
32
+ register('status') { Widgets::Status }
33
+
34
+ # Looks up a widget by handle
35
+ #
36
+ # ==== Raises
37
+ # Raises InvalidWidgetHandle if the widget is not available.
38
+ #
39
+ # ==== Returns
40
+ # A callable widget, to be invoked like `.call(argstring)`
41
+ #
42
+ sig { params(handle: String).returns(T.class_of(Widgets::Base)) }
43
+ def self.lookup(handle)
44
+ MAP.fetch(handle).call
45
+ rescue KeyError, NameError
46
+ raise(InvalidWidgetHandle, handle)
47
+ end
48
+
49
+ # All available widgets by name
50
+ #
51
+ sig { returns(T::Array[String]) }
52
+ def self.available
53
+ MAP.keys
54
+ end
55
+
56
+ class InvalidWidgetHandle < ArgumentError
57
+ extend T::Sig
58
+
59
+ sig { params(handle: String).void }
60
+ def initialize(handle)
61
+ super
62
+ @handle = handle
63
+ end
64
+
65
+ sig { returns(String) }
66
+ def message
67
+ keys = Widgets.available.join(',')
68
+ "invalid widget handle: #{@handle} " \
69
+ "-- must be one of CLI::UI::Widgets.available (#{keys})"
70
+ end
71
+ end
72
+
73
+ class InvalidWidgetArguments < ArgumentError
74
+ extend T::Sig
75
+
76
+ sig { params(argstring: String, pattern: Regexp).void }
77
+ def initialize(argstring, pattern)
78
+ super
79
+ @argstring = argstring
80
+ @pattern = pattern
81
+ end
82
+
83
+ sig { returns(String) }
84
+ def message
85
+ "invalid widget arguments: #{@argstring} " \
86
+ "-- must match pattern: #{@pattern.inspect}"
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,63 @@
1
+ # coding: utf-8
2
+
3
+ # typed: true
4
+
5
+ require 'cli/ui'
6
+ require 'cli/ui/frame/frame_stack'
7
+ require 'cli/ui/frame/frame_style'
8
+
9
+ module CLI
10
+ module UI
11
+ class Wrap
12
+ extend T::Sig
13
+
14
+ sig { params(input: String).void }
15
+ def initialize(input)
16
+ @input = input
17
+ end
18
+
19
+ sig { returns(String) }
20
+ def wrap
21
+ max_width = Terminal.width - Frame.prefix_width
22
+ width = T.let(0, Integer)
23
+ final = []
24
+ # Create an alternation of format codes of parameter lengths 1-20, since + and {1,n} not allowed in lookbehind
25
+ format_codes = (1..20).map { |n| /\x1b\[[\d;]{#{n}}m/ }.join('|')
26
+ codes = ''
27
+ @input.split(/(?=\s|\x1b\[[\d;]+m|\r)|(?<=\s|#{format_codes})/).each do |token|
28
+ case token
29
+ when '\x1B[0?m'
30
+ codes = ''
31
+ final << token
32
+ when /\x1b\[[\d;]+m/
33
+ codes += token # Track in use format codes so that they are resent after frame coloring
34
+ final << token
35
+ when "\n"
36
+ final << "\n#{codes}"
37
+ width = 0
38
+ when /\s/
39
+ token_width = ANSI.printing_width(token)
40
+ if width + token_width <= max_width
41
+ final << token
42
+ width += token_width
43
+ else
44
+ final << "\n#{codes}"
45
+ width = 0
46
+ end
47
+ else
48
+ token_width = ANSI.printing_width(token)
49
+ if width + token_width <= max_width
50
+ final << token
51
+ width += token_width
52
+ else
53
+ final << "\n#{codes}"
54
+ final << token
55
+ width = token_width
56
+ end
57
+ end
58
+ end
59
+ final.join
60
+ end
61
+ end
62
+ end
63
+ end