ballantine 0.1.4.pre.beta2 → 0.1.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 205e73804edf1a3ea9c16ddabb4dc3f5d1cc916300ff6f59576112153d8fadaa
4
- data.tar.gz: 3a742736e8db01a38761b0a395a94e7e16083edd35ff8cf460c77e4db0f797d5
3
+ metadata.gz: 7dc81ef643fe888582cb999e267066d56fde114d898a234122ea2165b79a6153
4
+ data.tar.gz: 823bb10cd43e75743c26fc61b65d2512229438b7232a3e779a20a53e7ff9bad1
5
5
  SHA512:
6
- metadata.gz: 41654e7d79f79ca6a0c5a556e567ec40f64f343797b92c748c6930d012c6cf49c9674878aa81ad9e7d50f42f8740208a0003f7bf9cde5e11bc674f0f8e8d0b5a
7
- data.tar.gz: 214c98d8b880faf7b68aeefa65a5670c688186d2b3e2f3098e2c3ed42cd80f221282ce441de10b6ea12e2569ec977f4062954100206fedcf0f5eae509ca70a26
6
+ metadata.gz: f55eb551e6c00ea8b6b1c59abfdae3d69742b7eab52cf8739a51d4d38918b4f77fe8f69f5e88c6418dec0e57cb4bb3892ea36ae64540ff19f79f31a01a5e3af0
7
+ data.tar.gz: 7abba991f1cb76e9f56d1685e06cd490d66bc48d6dff53d3078eae7ef42fe627028ee0b791aafb8ea1c9b82975e9ee36461d7a2d2f448518ab3d33870681a346
@@ -2,16 +2,22 @@
2
2
 
3
3
  module Ballantine
4
4
  class Author
5
+ include Printable
6
+
5
7
  attr_reader :name, :commits_hash
6
8
 
7
9
  class << self
8
10
  # @param [String] name
9
- # @return [Author] author
10
- def find_or_create_by(name:)
11
+ # @return [Author, NilClass]
12
+ def find(name:)
11
13
  @_collections = {} unless defined?(@_collections)
12
- return @_collections[name] unless @_collections[name].nil?
14
+ @_collections[name]
15
+ end
13
16
 
14
- @_collections[name] = new(name:)
17
+ # @param [String] name
18
+ # @return [Author]
19
+ def find_or_create_by(name:)
20
+ find(name:) || @_collections[name] = new(name:)
15
21
  end
16
22
 
17
23
  # @return [Array<Author>] authors
@@ -30,11 +36,15 @@ module Ballantine
30
36
 
31
37
  # @return [Boolean]
32
38
  def print_commits
39
+ conf.print_log(binding) if conf.verbose
40
+
33
41
  puts "\n" + "@#{name}".green
34
42
  commits_hash.each do |repo_name, commits|
35
43
  count, word = retrieve_count_and_word(commits)
36
- puts " > #{repo_name.blue}: #{count} new #{word}\n"
37
- puts commits.map(&:message)
44
+ puts " > #{repo_name.blue}: #{count} new #{word}"
45
+ commits.each do |commit|
46
+ puts_r " - #{commit.hash.yellow} #{commit.subject}", commit.url.gray
47
+ end
38
48
  end
39
49
 
40
50
  true
@@ -42,11 +52,14 @@ module Ballantine
42
52
 
43
53
  # returns an array to use slack attachments field
44
54
  # reference: https://api.slack.com/messaging/composing/layouts#building-attachments
45
- # @return [Hash] result
46
- def serialize_commits
55
+ # @return [Hash]
56
+ def slack_message
57
+ conf.print_log(binding) if conf.verbose
58
+
47
59
  message = commits_hash.map do |repo_name, commits|
48
60
  count, word = retrieve_count_and_word(commits)
49
- "*#{repo_name}*: #{count} new #{word}\n#{commits.map(&:message).join("\n")}"
61
+ "*#{repo_name}*: #{count} new #{word}\n" \
62
+ "#{commits.map(&:slack_message).join("\n")}"
50
63
  end.join("\n")
51
64
 
52
65
  {
@@ -57,6 +70,8 @@ module Ballantine
57
70
 
58
71
  private
59
72
 
73
+ def conf; Config.instance end
74
+
60
75
  # @param [Array<Commit>] commits
61
76
  # @param [Array(Integer, String)] count, word
62
77
  def retrieve_count_and_word(commits)
@@ -2,10 +2,9 @@
2
2
 
3
3
  module Ballantine
4
4
  class CLI < Thor
5
- TYPE_TERMINAL = "terminal"
6
- TYPE_SLACK = "slack"
5
+ include Printable
7
6
 
8
- attr_reader :send_type, :repo
7
+ attr_reader :repo
9
8
 
10
9
  class << self
11
10
  def exit_on_failure?; exit(1) end
@@ -23,8 +22,12 @@ module Ballantine
23
22
  end
24
23
 
25
24
  Config::AVAILABLE_ENVIRONMENTS.each { |env| option env, type: :boolean, default: false, desc: "Set envirment to `#{env}'." }
25
+ option "verbose", type: :boolean, default: false, desc: "Print a progress."
26
26
  desc "config [--env] [KEY] [VALUE]", "Set ballantine's configuration"
27
27
  def config(key = nil, value = nil)
28
+ conf.verbose = options["verbose"]
29
+ puts "$ ballantine config #{key} #{value}" if conf.verbose
30
+
28
31
  # check environment value
29
32
  if Config::AVAILABLE_ENVIRONMENTS.map { |key| !options[key] }.reduce(:&)
30
33
  raise NotAllowed, "Set environment value (#{Config::AVAILABLE_ENVIRONMENTS.map { |key| "`--#{key}'" }.join(", ")})"
@@ -32,31 +35,31 @@ module Ballantine
32
35
  raise NotAllowed, "Environment value must be unique."
33
36
  end
34
37
 
35
- @env = Config::AVAILABLE_ENVIRONMENTS.find { |key| options[key] }
36
- raise AssertionFailed, "Environment value must exist: #{@env}" if @env.nil?
38
+ env = Config::AVAILABLE_ENVIRONMENTS.find { |key| options[key] }
39
+ raise AssertionFailed, "Environment value must exist: #{env}" if env.nil?
37
40
 
41
+ conf.env = env
38
42
  value ? conf.set_data(key, value) : conf.print_data(key)
39
43
  end
40
44
 
45
+ option "verbose", type: :boolean, default: false, desc: "Print a progress."
46
+ option Config::TYPE_SLACK, type: :boolean, aliases: "-s", default: false, desc: "Send to slack using slack webhook URL."
41
47
  desc "diff [TARGET] [SOURCE]", "Diff commits between TARGET and SOURCE"
42
- option TYPE_SLACK, type: :boolean, aliases: "-s", default: false, desc: "Send to slack using slack webhook URL."
43
48
  def diff(target, source = %x(git rev-parse --abbrev-ref HEAD).chomp)
49
+ conf.verbose = options["verbose"]
50
+ puts "$ ballantine diff #{target} #{source}" if conf.verbose
51
+
44
52
  # validate arguments
45
53
  validate(target, source, **options)
46
54
 
47
- # check commits are newest
48
- system("git pull -f &> /dev/null")
49
-
50
55
  # init instance variables
51
56
  init_variables(target, source, **options)
52
57
 
53
58
  # check commits
54
59
  check_commits(**options)
55
60
 
56
- # send commits
57
- send_commits(target, source, **options)
58
-
59
- exit(0)
61
+ # print commits
62
+ print_commits(target, source, **options)
60
63
  end
61
64
 
62
65
  desc "version", "Display version information about ballntine"
@@ -68,13 +71,15 @@ module Ballantine
68
71
 
69
72
  private
70
73
 
71
- def conf; @conf ||= Config.new(@env) end
74
+ def conf; Config.instance end
72
75
 
73
76
  # @param [String] target
74
77
  # @param [String] source
75
78
  # @param [Hash] options
76
79
  # @return [NilClass] nil
77
80
  def validate(target, source, **options)
81
+ conf.print_log(binding) if conf.verbose
82
+
78
83
  if Dir[".git"].empty?
79
84
  raise NotAllowed, "ERROR: There is no \".git\" in #{Dir.pwd}."
80
85
  end
@@ -87,7 +92,7 @@ module Ballantine
87
92
  raise NotAllowed, "ERROR: target(#{target}) and source(#{source}) can't be equal."
88
93
  end
89
94
 
90
- if options[TYPE_SLACK] && !conf.get_data(Config::KEY_SLACK_WEBHOOK)
95
+ if options[Config::TYPE_SLACK] && !conf.get_data(Config::KEY_SLACK_WEBHOOK)
91
96
  raise NotAllowed, "ERROR: Can't find any slack webhook. Set slack webhook using `ballantine config --#{Config::ENV_LOCAL} slack_webhook [YOUR_WEBHOOK]'."
92
97
  end
93
98
 
@@ -99,8 +104,12 @@ module Ballantine
99
104
  # @param [Hash] options
100
105
  # @return [Boolean]
101
106
  def init_variables(target, source, **options)
102
- @send_type = options[TYPE_SLACK] ? TYPE_SLACK : TYPE_TERMINAL
103
- Repository.send_type = @send_type
107
+ conf.print_log(binding) if conf.verbose
108
+
109
+ # check commits are newest
110
+ system("git pull -f &> /dev/null")
111
+
112
+ conf.print_type = options[Config::TYPE_SLACK] ? Config::TYPE_SLACK : Config::TYPE_TERMINAL
104
113
  @repo = Repository.find_or_create_by(
105
114
  path: Dir.pwd,
106
115
  remote_url: %x(git config --get remote.origin.url).chomp,
@@ -114,6 +123,8 @@ module Ballantine
114
123
  # @param [Hash] options
115
124
  # @return [Boolean]
116
125
  def check_commits(**options)
126
+ conf.print_log(binding) if conf.verbose
127
+
117
128
  repo.check_commits
118
129
 
119
130
  true
@@ -123,24 +134,25 @@ module Ballantine
123
134
  # @param [String] source
124
135
  # @param [Hash] options
125
136
  # @return [Boolean]
126
- def send_commits(target, source, **options)
137
+ def print_commits(target, source, **options)
138
+ conf.print_log(binding) if conf.verbose
139
+
127
140
  authors = Author.all
128
141
  if authors.empty?
129
142
  raise ArgumentError, "ERROR: There is no commits between \"#{target}\" and \"#{source}\""
130
143
  end
131
144
 
132
145
  number = authors.size
133
- last_commit = repo.print_last_commit
134
146
 
135
- case send_type
136
- when TYPE_TERMINAL
137
- puts "Check commits before #{repo.name.red} deployment. (#{target.cyan} <- #{source.cyan})".ljust(Repository::DEFAULT_LJUST + 44) + " #{repo.url}/compare/#{repo.from.hash}...#{repo.to.hash}".gray
147
+ case conf.print_type
148
+ when Config::TYPE_TERMINAL
149
+ puts_r "Check commits before #{repo.name.red} deployment. (#{target.cyan}...#{source.cyan})", "#{repo.url}/compare/#{repo.from.hash}...#{repo.to.hash}".gray
138
150
  puts "Author".yellow + ": #{number}"
139
- puts "Last commit".blue + ": #{last_commit}"
151
+ puts_r "#{"Last commit".blue}: #{repo.to.hash.yellow} #{repo.to.subject}", repo.to.url.gray
140
152
  authors.map(&:print_commits)
141
- when TYPE_SLACK
153
+ when Config::TYPE_SLACK
142
154
  # set message for each author
143
- messages = authors.map(&:serialize_commits)
155
+ messages = authors.map(&:slack_message)
144
156
  actor = %x(git config user.name).chomp
145
157
 
146
158
  # send message to slack
@@ -151,15 +163,15 @@ module Ballantine
151
163
  request.content_type = "application/json"
152
164
  request.body = JSON.dump({
153
165
  "text" => ":white_check_mark: *#{repo.name}* deployment request by <@#{actor}>" \
154
- " (\`<#{repo.url}/tree/#{repo.from.hash}|#{target}>\` <- \`<#{repo.url}/tree/#{repo.to.hash}|#{source}>\` <#{repo.url}/compare/#{repo.from.hash}...#{repo.to.hash}|compare>)" \
155
- "\n:technologist: Author: #{number}\nLast commit: #{last_commit}",
166
+ " (\`<#{repo.url}/tree/#{repo.from.hash}|#{target}>\`<#{repo.url}/compare/#{repo.from.hash}...#{repo.to.hash}|...>\`<#{repo.url}/tree/#{repo.to.hash}|#{source}>\`)" \
167
+ "\n:technologist: Author: #{number}\nLast commit: #{repo.to.slack_message}",
156
168
  "attachments" => messages,
157
169
  })
158
170
  req_options = { use_ssl: uri.scheme == "https" }
159
171
  response = Net::HTTP.start(uri.hostname, uri.port, req_options) { |http| http.request(request) }
160
172
  puts response.message
161
173
  else
162
- raise AssertionFailed, "Unknown send type: #{send_type}"
174
+ raise AssertionFailed, "Unknown print type: #{conf.print_type}"
163
175
  end
164
176
 
165
177
  true
@@ -2,33 +2,45 @@
2
2
 
3
3
  module Ballantine
4
4
  class Commit
5
- attr_reader :hash, :message # attributes
5
+ attr_reader :hash, :long_hash, :subject # attributes
6
6
  attr_reader :repo, :author # associations
7
7
 
8
8
  class << self
9
9
  # @param [String] hash
10
10
  # @param [Repository] repo
11
- # @param [String] message
12
- # @param [Author, NilClass] message
13
- # @return [Commit]
14
- def find_or_create_by(hash:, repo:, message: nil, author: nil)
11
+ # @return [Commit, NilClass]
12
+ def find(hash:, repo:)
15
13
  @_collections = {} unless defined?(@_collections)
16
- index = "#{hash}-#{repo.name}"
17
- return @_collections[index] unless @_collections[index].nil?
14
+ @_collections["#{hash[...7]}-#{repo.name}"]
15
+ end
18
16
 
19
- @_collections[index] = new(hash:, repo:, message:, author:)
17
+ # @param [String] hash
18
+ # @param [Repository] repo
19
+ # @return [Commit]
20
+ def find_or_create_by(hash:, repo:)
21
+ find(hash:, repo:) || @_collections["#{hash[...7]}-#{repo.name}"] = new(hash:, repo:)
20
22
  end
21
23
  end
22
24
 
23
25
  # @param [String] hash
24
26
  # @param [Repository] repo
25
- # @param [String] message
26
- # @param [Author] author
27
- def initialize(hash:, repo:, message:, author:)
28
- @hash = hash
27
+ def initialize(hash:, repo:)
28
+ @hash = hash[...7]
29
29
  @repo = repo
30
- @message = message
31
- @author = author
30
+ end
31
+
32
+ # @return [Commit]
33
+ def update(**kwargs)
34
+ # TODO: validate keys and values
35
+ kwargs.each { |key, value| instance_variable_set("@#{key}", value) }
36
+ self
37
+ end
38
+
39
+ def url; @url ||= "#{repo.url}/commit/#{long_hash}" end
40
+
41
+ # @return [String]
42
+ def slack_message
43
+ "\`<#{url}|#{hash}>\` #{subject} - #{author.name}"
32
44
  end
33
45
  end
34
46
  end
@@ -2,26 +2,40 @@
2
2
 
3
3
  module Ballantine
4
4
  class Config
5
+ FILE_BALLANTINE_CONFIG = ".ballantine.json"
5
6
  ENV_LOCAL = "local"
6
7
  ENV_GLOBAL = "global"
8
+ TYPE_TERMINAL = "terminal"
9
+ TYPE_SLACK = "slack"
7
10
  AVAILABLE_ENVIRONMENTS = [
8
11
  ENV_LOCAL,
9
12
  ENV_GLOBAL,
10
13
  ].freeze
11
-
12
14
  KEY_SLACK_WEBHOOK = "slack_webhook"
13
15
  AVAILABLE_KEYS = [
14
16
  KEY_SLACK_WEBHOOK,
15
17
  ].freeze
18
+ AVAILABLE_PRINT_INSTANCE_VARIABLES = [:@name, :@from, :@to].freeze
16
19
 
17
- FILE_BALLANTINE_CONFIG = ".ballantine.json"
20
+ attr_reader :data, :loaded
21
+ attr_accessor :env, :print_type, :verbose
18
22
 
19
- attr_reader :env, :data, :loaded
23
+ class << self
24
+ # @note singleton method
25
+ # @return [Config]
26
+ def instance(...)
27
+ return @_instance if defined?(@_instance)
20
28
 
21
- def initialize(env)
22
- @env = env || ENV_LOCAL
29
+ @_instance = new(...)
30
+ end
31
+ end
32
+
33
+ def initialize
34
+ @env = ENV_LOCAL
23
35
  @data = {}
24
36
  @loaded = false
37
+ @print_type = TYPE_TERMINAL
38
+ @verbose = false
25
39
  end
26
40
 
27
41
  # @param [Hash] options
@@ -87,6 +101,18 @@ module Ballantine
87
101
  @data[key]
88
102
  end
89
103
 
104
+ # @param [Binding] binding
105
+ # @return [NilClass]
106
+ def print_log(binding)
107
+ method = caller(1..1)[0][/`([^']*)'/, 1]
108
+
109
+ puts [
110
+ "#{binding.receiver.class.name}##{method}",
111
+ (binding.receiver.instance_variables & AVAILABLE_PRINT_INSTANCE_VARIABLES).map { |var| "#{var}:#{binding.receiver.instance_variable_get(var).inspect}" }.join(" "),
112
+ binding.receiver.method(method).parameters.map { |_, arg| arg }.map { |arg| "#{arg}:#{binding.local_variable_get(arg)}" }.join(" "),
113
+ ].compact.join("\t")
114
+ end
115
+
90
116
  private
91
117
 
92
118
  def file_path(env = @env)
@@ -13,21 +13,24 @@ module Ballantine
13
13
  '^ssh://git@(.+)/(.+)/(.+)\.git$', # protocol: ssh -> ssh://git@github.com/oohyun15/ballantine.git
14
14
  ].freeze
15
15
  FILE_GITMODULES = ".gitmodules"
16
- DEFAULT_LJUST = 70
17
16
  PARSER_TOKEN = "!#!#"
18
17
 
19
- attr_reader :name, :path, :owner, :url, :from, :to, :format # attributes
18
+ attr_reader :name, :path, :owner, :from, :to # attributes
20
19
  attr_reader :main_repo, :sub_repos, :commits # associations
21
20
 
22
21
  class << self
22
+ # @param [String] path
23
+ # @return [Repository, NilClass]
24
+ def find(path:)
25
+ @_collections = {} unless defined?(@_collections)
26
+ @_collections[path]
27
+ end
28
+
23
29
  # @param [String] path
24
30
  # @param [String] remote_url
25
31
  # @return [Repository]
26
32
  def find_or_create_by(path:, remote_url: nil)
27
- @_collections = {} unless defined?(@_collections)
28
- return @_collections[path] unless @_collections[path].nil?
29
-
30
- @_collections[path] = new(path:, remote_url:)
33
+ find(path:) || @_collections[path] = new(path:, remote_url:)
31
34
  end
32
35
 
33
36
  # @return [Array<Repository>]
@@ -36,9 +39,6 @@ module Ballantine
36
39
 
37
40
  @_collections.values
38
41
  end
39
-
40
- def send_type; @_send_type end
41
- def send_type=(value); @_send_type = value end
42
42
  end
43
43
 
44
44
  # @param [String] path
@@ -51,14 +51,16 @@ module Ballantine
51
51
  str = remote_url.match(regex)
52
52
  break [str[2], str[3]] if str
53
53
  end
54
- @url = "https://github.com/#{owner}/#{name}"
55
- @format = check_format
56
54
  end
57
55
 
56
+ def url; @url ||= "https://github.com/#{owner}/#{name}" end
57
+
58
58
  # @param [String] target
59
59
  # @param [String] source
60
60
  # @return [Boolean]
61
61
  def init_variables(target, source)
62
+ conf.print_log(binding) if conf.verbose
63
+
62
64
  current_revision = %x(git rev-parse --abbrev-ref HEAD).chomp
63
65
 
64
66
  foo = lambda do |hash, context|
@@ -76,7 +78,7 @@ module Ballantine
76
78
  if sub_repos.any?
77
79
  %x(git ls-tree HEAD #{sub_repos.map(&:path).join(" ")}).split("\n").map do |line|
78
80
  _, _, sub_hash, sub_path = line.split(" ")
79
- sub_repo = Repository.find_or_create_by(
81
+ sub_repo = Repository.find(
80
82
  path: path + "/" + sub_path,
81
83
  )
82
84
  sub_commit = Commit.find_or_create_by(
@@ -98,6 +100,8 @@ module Ballantine
98
100
 
99
101
  # @return [Boolean]
100
102
  def check_commits
103
+ conf.print_log(binding) if conf.verbose
104
+
101
105
  authors = retrieve_authors
102
106
  authors.each do |author|
103
107
  commits = retrieve_commits(author)
@@ -120,16 +124,9 @@ module Ballantine
120
124
  true
121
125
  end
122
126
 
123
- # @return [String]
124
- def print_last_commit
125
- %x(git --no-pager log --reverse --format="#{check_format(ljust: DEFAULT_LJUST - 12)}" --abbrev=7 #{from.hash}..#{to.hash} -1).strip
126
- end
127
-
128
127
  private
129
128
 
130
- def send_type
131
- self.class.send_type
132
- end
129
+ def conf; Config.instance end
133
130
 
134
131
  # @param [String] name
135
132
  # @return [String] hash
@@ -141,16 +138,15 @@ module Ballantine
141
138
  %x(git rev-list -n 1 #{name}).chomp[0...7]
142
139
  end
143
140
 
144
- # @param [Integer] ljust
145
141
  # @return [String]
146
- def check_format(ljust: DEFAULT_LJUST)
147
- case send_type
148
- when CLI::TYPE_TERMINAL
142
+ def check_format
143
+ case conf.print_type
144
+ when Config::TYPE_TERMINAL
149
145
  " - " + "%h".yellow + " %<(#{ljust})%s " + "#{url}/commit/%H".gray
150
- when CLI::TYPE_SLACK
146
+ when Config::TYPE_SLACK
151
147
  "\\\`<#{url}/commit/%H|%h>\\\` %s - %an"
152
148
  else
153
- raise AssertionFailed, "Unknown send type: #{send_type}"
149
+ raise AssertionFailed, "Unknown print type: #{conf.print_type}"
154
150
  end
155
151
  end
156
152
 
@@ -187,19 +183,26 @@ module Ballantine
187
183
  # @param [Author] author
188
184
  # @return [Array<Commit>]
189
185
  def retrieve_commits(author)
186
+ command = <<~CMD.tr("\n", " ").strip
187
+ git --no-pager log --reverse --no-merges --author="#{author.name}"
188
+ --format="%h#{PARSER_TOKEN}%H#{PARSER_TOKEN}%s"
189
+ --abbrev=7 #{from.hash}..#{to.hash}
190
+ CMD
190
191
  results =
191
- %x(git --no-pager log --reverse --no-merges --author="#{author.name}" --format="%h#{PARSER_TOKEN}#{format}" --abbrev=7 #{from.hash}..#{to.hash})
192
+ %x(#{command})
192
193
  .gsub('"', '\"')
193
194
  .gsub(/[\u0080-\u00ff]/, "")
194
195
  .split("\n")
195
196
 
196
197
  results.map do |result|
197
- hash, message = result.split(PARSER_TOKEN)
198
+ hash, long_hash, subject = result.split(PARSER_TOKEN)
198
199
  Commit.find_or_create_by(
199
200
  hash: hash,
200
201
  repo: self,
201
- message: message,
202
+ ).update(
202
203
  author: author,
204
+ long_hash: long_hash,
205
+ subject: subject,
203
206
  )
204
207
  end
205
208
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ballantine
4
- VERSION = "0.1.4-beta2"
4
+ VERSION = "0.1.4"
5
5
  end
data/lib/ballantine.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require "thor"
4
4
  require "json"
5
5
  require_relative "string"
6
+ require_relative "printable"
6
7
  require_relative "ballantine/version"
7
8
  require_relative "ballantine/config"
8
9
  require_relative "ballantine/author"
data/lib/printable.rb ADDED
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Printable
4
+ # @param [String] msg
5
+ # @param [String] msg_r
6
+ # @return [NilClass]
7
+ def puts_r(msg, msg_r)
8
+ size = rjust_size(msg, msg_r)
9
+ puts msg + msg_r.rjust(size)
10
+ end
11
+
12
+ # @param [String] msg
13
+ # @param [String] msg_r
14
+ # @return [Integer]
15
+ def rjust_size(msg, msg_r)
16
+ sanitized = ->(str) { str.sanitize_colored.size + str.scan(/\p{Hangul}/).size }
17
+ cols - sanitized.call(msg) - sanitized.call(msg_r) + msg_r.size
18
+ end
19
+
20
+ # @return [Integer]
21
+ def cols
22
+ return @_cols if defined?(@_cols)
23
+
24
+ require "io/console"
25
+ _lines, @_cols = IO.console.winsize
26
+ @_cols
27
+ end
28
+ end
data/lib/string.rb CHANGED
@@ -16,4 +16,6 @@ class String
16
16
  def yellow; "#{YELLOW}#{self}#{NC}" end
17
17
  def blue; "#{BLUE}#{self}#{NC}" end
18
18
  def cyan; "#{CYAN}#{self}#{NC}" end
19
+
20
+ def sanitize_colored; gsub(/\e\[\d+;?\d*m/, "") end
19
21
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ballantine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4.pre.beta2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - oohyun15
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-24 00:00:00.000000000 Z
11
+ date: 2023-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -55,6 +55,7 @@ files:
55
55
  - lib/ballantine/config.rb
56
56
  - lib/ballantine/repository.rb
57
57
  - lib/ballantine/version.rb
58
+ - lib/printable.rb
58
59
  - lib/string.rb
59
60
  homepage: https://github.com/oohyun15/ballantine
60
61
  licenses:
@@ -71,9 +72,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
71
72
  version: '3.1'
72
73
  required_rubygems_version: !ruby/object:Gem::Requirement
73
74
  requirements:
74
- - - ">"
75
+ - - ">="
75
76
  - !ruby/object:Gem::Version
76
- version: 1.3.1
77
+ version: '0'
77
78
  requirements: []
78
79
  rubygems_version: 3.3.26
79
80
  signing_key: