cocoapods-tdf-bin 0.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.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +103 -0
  4. data/lib/cocoapods-tdf-bin.rb +2 -0
  5. data/lib/cocoapods-tdf-bin/command.rb +2 -0
  6. data/lib/cocoapods-tdf-bin/command/bin.rb +57 -0
  7. data/lib/cocoapods-tdf-bin/command/bin/archive.rb +222 -0
  8. data/lib/cocoapods-tdf-bin/command/bin/auto.rb +216 -0
  9. data/lib/cocoapods-tdf-bin/command/bin/code.rb +232 -0
  10. data/lib/cocoapods-tdf-bin/command/bin/imy.rb +46 -0
  11. data/lib/cocoapods-tdf-bin/command/bin/init.rb +69 -0
  12. data/lib/cocoapods-tdf-bin/command/bin/initHotKey.rb +70 -0
  13. data/lib/cocoapods-tdf-bin/command/bin/install.rb +44 -0
  14. data/lib/cocoapods-tdf-bin/command/bin/lib/lint.rb +69 -0
  15. data/lib/cocoapods-tdf-bin/command/bin/repo/update.rb +43 -0
  16. data/lib/cocoapods-tdf-bin/command/bin/spec/create.rb +73 -0
  17. data/lib/cocoapods-tdf-bin/command/bin/spec/push.rb +114 -0
  18. data/lib/cocoapods-tdf-bin/command/bin/update.rb +157 -0
  19. data/lib/cocoapods-tdf-bin/config/config.rb +138 -0
  20. data/lib/cocoapods-tdf-bin/config/config_asker.rb +57 -0
  21. data/lib/cocoapods-tdf-bin/config/config_builder.rb +238 -0
  22. data/lib/cocoapods-tdf-bin/config/config_hot_key.rb +103 -0
  23. data/lib/cocoapods-tdf-bin/config/config_hot_key_asker.rb +57 -0
  24. data/lib/cocoapods-tdf-bin/gem_version.rb +10 -0
  25. data/lib/cocoapods-tdf-bin/helpers.rb +5 -0
  26. data/lib/cocoapods-tdf-bin/helpers/Info.plist +0 -0
  27. data/lib/cocoapods-tdf-bin/helpers/build_helper.rb +162 -0
  28. data/lib/cocoapods-tdf-bin/helpers/build_utils.rb +101 -0
  29. data/lib/cocoapods-tdf-bin/helpers/framework.rb +85 -0
  30. data/lib/cocoapods-tdf-bin/helpers/framework_builder.rb +283 -0
  31. data/lib/cocoapods-tdf-bin/helpers/library.rb +54 -0
  32. data/lib/cocoapods-tdf-bin/helpers/library_builder.rb +90 -0
  33. data/lib/cocoapods-tdf-bin/helpers/sources_helper.rb +36 -0
  34. data/lib/cocoapods-tdf-bin/helpers/spec_creator.rb +168 -0
  35. data/lib/cocoapods-tdf-bin/helpers/spec_files_helper.rb +77 -0
  36. data/lib/cocoapods-tdf-bin/helpers/spec_source_creator.rb +228 -0
  37. data/lib/cocoapods-tdf-bin/helpers/upload_helper.rb +89 -0
  38. data/lib/cocoapods-tdf-bin/native.rb +23 -0
  39. data/lib/cocoapods-tdf-bin/native/acknowledgements.rb +27 -0
  40. data/lib/cocoapods-tdf-bin/native/analyzer.rb +55 -0
  41. data/lib/cocoapods-tdf-bin/native/configuration.rb +26 -0
  42. data/lib/cocoapods-tdf-bin/native/file_accessor.rb +28 -0
  43. data/lib/cocoapods-tdf-bin/native/installation_options.rb +25 -0
  44. data/lib/cocoapods-tdf-bin/native/installer.rb +135 -0
  45. data/lib/cocoapods-tdf-bin/native/linter.rb +26 -0
  46. data/lib/cocoapods-tdf-bin/native/path_source.rb +33 -0
  47. data/lib/cocoapods-tdf-bin/native/pod_source_installer.rb +19 -0
  48. data/lib/cocoapods-tdf-bin/native/pod_target_installer.rb +94 -0
  49. data/lib/cocoapods-tdf-bin/native/podfile.rb +91 -0
  50. data/lib/cocoapods-tdf-bin/native/podfile_env.rb +37 -0
  51. data/lib/cocoapods-tdf-bin/native/podfile_generator.rb +199 -0
  52. data/lib/cocoapods-tdf-bin/native/podspec_finder.rb +25 -0
  53. data/lib/cocoapods-tdf-bin/native/resolver.rb +243 -0
  54. data/lib/cocoapods-tdf-bin/native/sandbox_analyzer.rb +34 -0
  55. data/lib/cocoapods-tdf-bin/native/source.rb +35 -0
  56. data/lib/cocoapods-tdf-bin/native/sources_manager.rb +20 -0
  57. data/lib/cocoapods-tdf-bin/native/specification.rb +31 -0
  58. data/lib/cocoapods-tdf-bin/native/target_validator.rb +41 -0
  59. data/lib/cocoapods-tdf-bin/native/validator.rb +40 -0
  60. data/lib/cocoapods-tdf-bin/source_provider_hook.rb +54 -0
  61. data/lib/cocoapods_plugin.rb +3 -0
  62. data/spec/command/bin_spec.rb +12 -0
  63. data/spec/spec_helper.rb +50 -0
  64. metadata +179 -0
@@ -0,0 +1,138 @@
1
+ require 'yaml'
2
+ require 'cocoapods-tdf-bin/native/podfile'
3
+ require 'cocoapods-tdf-bin/native/podfile_env'
4
+ require 'cocoapods/generate'
5
+
6
+ module CBin
7
+ class Config
8
+ def config_file
9
+ config_file_with_configuration_env(configuration_env)
10
+ end
11
+
12
+ def template_hash
13
+ {
14
+ 'configuration_env' => { description: '编译环境', default: 'dev', selection: %w[dev debug_iphoneos release_iphoneos] },
15
+ 'code_repo_url' => { description: '源码私有源 Git 地址', default: 'git@github.com:su350380433/example_spec_source.git' },
16
+ 'binary_repo_url' => { description: '二进制私有源 Git 地址', default: 'git@github.com:su350380433/example_spec_bin_dev.git' },
17
+ 'binary_download_url' => { description: '二进制下载地址,内部会依次传入组件名称与版本,替换字符串中的 %s ', default: 'http://localhost:8080/download/%s/%s/zip' },
18
+ 'binary_upload_url' => { description: '二进制下载地址,内部会依次传入组件名称与版本,替换字符串中的 %s ', default: 'http://localhost:8080/upload/%s/%s/zip' },
19
+ # 'binary_type' => { description: '二进制打包类型', default: 'framework', selection: %w[framework library] },
20
+ 'download_file_type' => { description: '下载二进制文件类型', default: 'zip', selection: %w[zip tgz tar tbz txz dmg] }
21
+ }
22
+ end
23
+
24
+ def config_file_with_configuration_env(configuration_env)
25
+ file = config_dev_file
26
+ if configuration_env == "release_iphoneos"
27
+ file = config_release_iphoneos_file
28
+ puts "\n====== #{configuration_env} 环境 ========"
29
+ elsif configuration_env == "debug_iphoneos"
30
+ file = config_debug_iphoneos_file
31
+ puts "\n====== #{configuration_env} 环境 ========"
32
+ elsif configuration_env == "dev"
33
+ puts "\n====== #{configuration_env} 环境 ========"
34
+ else
35
+ raise "\n===== #{configuration_env} 参数有误,请检查%w[dev debug_iphoneos release_iphoneos]===="
36
+ end
37
+
38
+ File.expand_path("#{Pod::Config.instance.home_dir}/#{file}")
39
+ end
40
+
41
+ def configuration_env
42
+ #如果是dev 再去 podfile的配置文件中获取,确保是正确的, pod update时会用到
43
+ if @configuration_env == "dev" || @configuration_env == nil
44
+ if Pod::Config.instance.podfile
45
+ configuration_env ||= Pod::Config.instance.podfile.configuration_env
46
+ end
47
+ configuration_env ||= "dev"
48
+ @configuration_env = configuration_env
49
+ end
50
+ @configuration_env
51
+ end
52
+
53
+ #上传的url
54
+ def bin_upload_url
55
+ cut_string = "/%s/%s/zip"
56
+ binary_upload_url[0,binary_upload_url.length - cut_string.length]
57
+ end
58
+
59
+ def set_configuration_env(env)
60
+ @configuration_env = env
61
+ end
62
+
63
+ #包含arm64 armv7架构,xcodebuild 是Debug模式
64
+ def config_debug_iphoneos_file
65
+ "bin_debug_iphoneos.yml"
66
+ end
67
+ #包含arm64 armv7架构,xcodebuild 是Release模式
68
+ def config_release_iphoneos_file
69
+ "bin_release_iphoneos.yml"
70
+ end
71
+ #包含x86 arm64 armv7架构,xcodebuild 是Release模式
72
+ def config_dev_file
73
+ "bin_dev.yml"
74
+ end
75
+
76
+ def sync_config(config)
77
+ File.open(config_file_with_configuration_env(config['configuration_env']), 'w+') do |f|
78
+ f.write(config.to_yaml)
79
+ end
80
+ end
81
+
82
+ def default_config
83
+ @default_config ||= Hash[template_hash.map { |k, v| [k, v[:default]] }]
84
+ end
85
+
86
+ private
87
+
88
+ def load_config
89
+ if File.exist?(config_file)
90
+ YAML.load_file(config_file)
91
+ else
92
+ default_config
93
+ end
94
+ end
95
+
96
+ def config
97
+ @config ||= begin
98
+ puts "====== cocoapods-tdf-bin #{CBin::VERSION} 版本 ======== \n"
99
+ @config = OpenStruct.new load_config
100
+ validate!
101
+ @config
102
+ end
103
+ end
104
+
105
+ def validate!
106
+ template_hash.each do |k, v|
107
+ selection = v[:selection]
108
+ next if !selection || selection.empty?
109
+
110
+ config_value = @config.send(k)
111
+ next unless config_value
112
+ unless selection.include?(config_value)
113
+ raise Pod::Informative, "#{k} 字段的值必须限定在可选值 [ #{selection.join(' / ')} ] 内".red
114
+ end
115
+ end
116
+ end
117
+
118
+ def respond_to_missing?(method, include_private = false)
119
+ config.respond_to?(method) || super
120
+ end
121
+
122
+ def method_missing(method, *args, &block)
123
+ if config.respond_to?(method)
124
+ config.send(method, *args)
125
+ elsif template_hash.keys.include?(method.to_s)
126
+ raise Pod::Informative, "#{method} 字段必须在配置文件 #{config_file} 中设置, 请执行 init 命令配置或手动修改配置文件".red
127
+ else
128
+ super
129
+ end
130
+ end
131
+ end
132
+
133
+ def self.config
134
+ @config ||= Config.new
135
+ end
136
+
137
+
138
+ end
@@ -0,0 +1,57 @@
1
+ require 'yaml'
2
+ require 'cocoapods-tdf-bin/config/config'
3
+
4
+ module CBin
5
+ class Config
6
+ class Asker
7
+ def show_prompt
8
+ print ' > '.green
9
+ end
10
+
11
+ def ask_with_answer(question, pre_answer, selection)
12
+ print "\n#{question}\n"
13
+
14
+ print_selection_info = lambda {
15
+ print "可选值:[ #{selection.join(' / ')} ]\n" if selection
16
+ }
17
+ print_selection_info.call
18
+ print "旧值:#{pre_answer}\n" unless pre_answer.nil?
19
+
20
+ answer = ''
21
+ loop do
22
+ show_prompt
23
+ answer = STDIN.gets.chomp.strip
24
+
25
+ if answer == '' && !pre_answer.nil?
26
+ answer = pre_answer
27
+ print answer.yellow
28
+ print "\n"
29
+ end
30
+
31
+ next if answer.empty?
32
+ break if !selection || selection.include?(answer)
33
+
34
+ print_selection_info.call
35
+ end
36
+
37
+ answer
38
+ end
39
+
40
+ def wellcome_message
41
+ print <<~EOF
42
+
43
+ 开始设置二进制化初始信息.
44
+ 所有的信息都会保存在 #{CBin.config.config_file} 文件中.
45
+ %w[bin_dev.yml bin_debug_iphoneos.yml bin_release_iphoneos.yml]
46
+ 你可以在对应目录下手动添加编辑该文件. 文件包含的配置信息样式如下:
47
+
48
+ #{CBin.config.default_config.to_yaml}
49
+ EOF
50
+ end
51
+
52
+ def done_message
53
+ print "\n设置完成.\n".green
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,238 @@
1
+ require 'yaml'
2
+
3
+ module CBin
4
+ class Config
5
+ class Builder
6
+
7
+ include Pod
8
+
9
+ def self.instance
10
+ @instance ||= new
11
+ end
12
+
13
+ def initialize
14
+ load_build_config
15
+ # clean
16
+ end
17
+
18
+ # 加载配置项
19
+ def load_build_config
20
+ @white_pod_list = []
21
+ @build_pod_list = []
22
+ @ignore_git_list = []
23
+ project_root = Pod::Config.instance.project_root
24
+ path = File.join(project_root.to_s, 'BinArchive.json')
25
+
26
+ if File.exist?(path)
27
+ config = JSON.parse(File.read(path))
28
+ if config['archive-white-pod-list']
29
+ @white_pod_list = config['archive-white-pod-list']
30
+ end
31
+
32
+ if config['archive-build-pod-list']
33
+ @build_pod_list = config['archive-build-pod-list']
34
+ end
35
+
36
+ UI.warn "====== archive-build-pod-list = #{@build_pod_list}" if @build_pod_list
37
+
38
+ UI.warn "====== archive-white-pod-list = #{@white_pod_list}" if @white_pod_list
39
+ @ignore_git_list = config['ignore-git-list']
40
+ UI.warn "====== ignore_git_list = #{@ignore_git_list}" if @ignore_git_list
41
+ @ignore_http_list = config['ignore-http-list']
42
+
43
+ @xcode_build_name = config['xcode_build_path']
44
+ @root_dir = config['root_dir'] unless config['root_dir'].nil?
45
+ end
46
+
47
+ end
48
+
49
+ def clean
50
+ #清除之前的缓存
51
+ FileUtils.rm_rf(Dir.glob("#{zip_dir}/*")) if File.exist?(zip_dir)
52
+ FileUtils.rm_rf(Dir.glob("#{binary_json_dir}/*")) if File.exist?(binary_json_dir)
53
+ FileUtils.rm_rf(Dir.glob("#{local_psec_dir}/*")) if File.exist?(local_psec_dir)
54
+ end
55
+
56
+ # 制作二进制打包 工程目录
57
+ def gen_name
58
+ 'bin-archive'
59
+ end
60
+
61
+ # 制作二进制打包 工程目录
62
+ def gen_dir
63
+ @gen_dir ||= begin
64
+ dir = File.join(root_dir,gen_name)
65
+ Dir.mkdir(dir) unless File.exist?dir
66
+ Pathname.new(dir)
67
+ end
68
+ end
69
+
70
+
71
+ def framework_name(spec)
72
+ "#{spec.name}.framework"
73
+ end
74
+
75
+ def framework_name_version(spec)
76
+ "#{spec.name}.framework_#{spec.version}"
77
+ end
78
+
79
+ def framework_zip_file(spec)
80
+ File.join(zip_dir_name, framework_name_version(spec))
81
+ end
82
+
83
+ def framework_file(spec)
84
+ File.join(zip_dir_name, framework_name(spec))
85
+ end
86
+
87
+ def library_name(spec)
88
+ library_name_version(spec.name, spec.version)
89
+ end
90
+
91
+ def library_name_version(name,version)
92
+ "bin_#{name}_#{version}"
93
+ end
94
+ def library_file(spec)
95
+ File.join(zip_dir_name, library_name(spec))
96
+ end
97
+
98
+ def zip_dir_name
99
+ "bin-zip"
100
+ end
101
+
102
+ def zip_dir
103
+ @zip_dir ||= begin
104
+ dir = File.join(root_dir,zip_dir_name)
105
+ Dir.mkdir(dir) unless File.exist?dir
106
+ Pathname.new(dir)
107
+ end
108
+ end
109
+
110
+ #本地
111
+ def local_spec_dir_name
112
+ "bin-spec"
113
+ end
114
+
115
+ def local_psec_dir
116
+ @local_psec_dir ||= begin
117
+ dir = File.join(root_dir,local_spec_dir_name)
118
+ Dir.mkdir(dir) unless File.exist?dir
119
+ Pathname.new(dir)
120
+ end
121
+ end
122
+
123
+ def binary_json_dir_name
124
+ "bin-json"
125
+ end
126
+
127
+ def binary_json_dir
128
+ @binary_json_dir ||= begin
129
+ dir = File.join(root_dir,binary_json_dir_name)
130
+ Dir.mkdir(dir) unless File.exist?dir
131
+ Pathname.new(dir)
132
+ end
133
+ end
134
+
135
+
136
+
137
+ #编译target名,如 seeyou
138
+ def target_name
139
+ # podfile_path = Pod::Config.instance.installation_root.to_s + "/Example/podfile"
140
+ # begin
141
+ # podfile = Pod::Podfile.from_file(podfile_path)
142
+ # rescue
143
+ # podfile = Pod::Config.instance.podfile
144
+ # end
145
+ @target_name ||= begin
146
+ target_name_str = Pod::Config.instance.podfile.root_target_definitions.first.children.first.to_s
147
+ target_name_str[5,target_name_str.length]
148
+ end
149
+ end
150
+
151
+ #编译缓存文件目录,如Xcodebuild的编译缓存目录
152
+ # 如果有配置, 配置完整路径,会使用
153
+ def xcode_build_name
154
+ @xcode_build_name ||= begin
155
+ project_root = Pod::Config.instance.project_root
156
+ path = File.join(project_root.to_s, 'BinArchive.json')
157
+
158
+ if File.exist?(path)
159
+ config = JSON.parse(File.read(path))
160
+ @xcode_build_name = config['xcode_build_path']
161
+ end
162
+ #默认值,在美柚上使用默认
163
+ if @xcode_build_name.nil? || Dir.exist?(@xcode_build_name)
164
+ @xcode_build_name = "xcode-build/Build/Intermediates.noindex/ArchiveIntermediates/#{target_name}/IntermediateBuildFilesPath/UninstalledProducts/iphoneos/"
165
+ end
166
+ puts @xcode_build_name
167
+ @xcode_build_name
168
+ end
169
+ end
170
+
171
+
172
+ #完整的xcodebuild 输出路径
173
+ def xcode_build_dir
174
+ @xcode_build_dir ||= begin
175
+ temp_xcode_build_name = xcode_build_name
176
+ if File.exist?(temp_xcode_build_name)
177
+ Pathname.new(temp_xcode_build_name)
178
+ else
179
+ dir = File.join(root_dir,xcode_build_name)
180
+ Pathname.new(dir)
181
+ end
182
+ end
183
+ end
184
+ #完整的xcodebuild BuildProductsPath输出路径,
185
+ def xcode_BuildProductsPath_dir
186
+ @xcode_BuildProductsPath_dir ||= begin
187
+ temp_xcode_BuildProductsPath_dir = "xcode-build/Build/Intermediates.noindex/ArchiveIntermediates/#{target_name}/BuildProductsPath/"
188
+ full_path = File.join(root_dir, temp_xcode_BuildProductsPath_dir)
189
+
190
+ if (File.exist?(full_path))
191
+ Dir.chdir(full_path) do
192
+ iphoneos = Dir.glob('*-iphoneos')
193
+ if iphoneos.length > 0
194
+ full_path = File.join(full_path,iphoneos.first)
195
+ else
196
+ UI.warn "====== 找不到 *-iphoneos @xcode_BuildProductsPath_dir = #{@xcode_BuildProductsPath_dir}"
197
+ end
198
+ end
199
+ end
200
+ Pathname.new(full_path)
201
+ end
202
+ end
203
+
204
+
205
+ #处理编译产物后存储根目录,会存放spec、 json、zip的父目录,默认是工程的同级目录下,"#{basename}-build-temp"
206
+ def root_dir
207
+ @root_dir ||= begin
208
+ basename = File.basename(Pod::Config.instance.installation_root)
209
+ parent_dir = File.dirname(Pod::Config.instance.installation_root)
210
+ root_name = File.join(parent_dir,"#{basename}-build-temp")
211
+ Dir.mkdir(root_name) unless File.exist?root_name
212
+ Pathname.new(root_name)
213
+ end
214
+
215
+ end
216
+
217
+ # 需要制作二进制名单,为空默认为全部
218
+ def build_pod_list
219
+ @build_pod_list
220
+ end
221
+
222
+ #制作二进制 白名单
223
+ def white_pod_list
224
+ @white_pod_list
225
+ end
226
+
227
+ #忽略制作二进制组件的 git
228
+ def ignore_git_list
229
+ @ignore_git_list
230
+ end
231
+
232
+ def ignore_http_list
233
+ @ignore_http_list
234
+ end
235
+
236
+ end
237
+ end
238
+ end
@@ -0,0 +1,103 @@
1
+ require 'yaml'
2
+ require 'cocoapods-tdf-bin/native/podfile'
3
+ require 'cocoapods-tdf-bin/native/podfile_env'
4
+ require 'cocoapods/generate'
5
+
6
+ module CBin
7
+ class Config_Hot_Key
8
+
9
+ def config_file
10
+ config_file_with_hot_key_index(hot_key_index)
11
+ end
12
+
13
+ def template_hash
14
+ {
15
+ 'hot_key_index' => { description: '快捷键', default: '1', selection: %w[1 2 3...] },
16
+ 'hot_key_dir' => { description: '快捷键执行目录', default: '' },
17
+ 'hot_key_cmd' => { description: '快捷键执行命令', default: 'pod bin update --no-repo-update' }
18
+ }
19
+ end
20
+
21
+ def config_file_with_hot_key_index(hot_key_index)
22
+ file = config_file_whith_hot_key_index(hot_key_index)
23
+ raise "\n===== #{hot_key_index} 参数有误,请检查%w[1 2 3...]===" unless (hot_key_index.to_i).is_a?(Integer)
24
+ File.expand_path("#{Pod::Config.instance.home_dir}/#{file}")
25
+ end
26
+
27
+ def hot_key_index
28
+ @hot_key_index = 1 if @hot_key_index.is_a?(NilClass)
29
+ @hot_key_index
30
+ end
31
+
32
+ def set_hot_key_index(hot_key_index)
33
+ @hot_key_index = hot_key_index
34
+ end
35
+
36
+ def config_file_whith_hot_key_index(hot_key_index)
37
+ "hot_key_#{hot_key_index}.yml"
38
+ end
39
+
40
+ def sync_config(config)
41
+ File.open(config_file_with_hot_key_index(config['hot_key_index']), 'w+') do |f|
42
+ f.write(config.to_yaml)
43
+ end
44
+ end
45
+
46
+ def default_config
47
+ @default_config ||= Hash[template_hash.map { |k, v| [k, v[:default]] }]
48
+ end
49
+
50
+ private
51
+
52
+ def load_config
53
+ file = config_file
54
+ if (!file.nil?) && File.exist?(config_file)
55
+ YAML.load_file(config_file)
56
+ else
57
+ default_config
58
+ end
59
+ end
60
+
61
+ def config
62
+ @config ||= begin
63
+ puts "====== cocoapods-tdf-bin #{CBin::VERSION} 版本 ======== \n"
64
+ @config = OpenStruct.new load_config
65
+ validate!
66
+ @config
67
+ end
68
+ end
69
+
70
+ def validate!
71
+ template_hash.each do |k, v|
72
+ selection = v[:selection]
73
+ next if !selection || selection.empty?
74
+
75
+ config_value = @config.send(k)
76
+ next unless config_value
77
+ unless selection.include?(config_value)
78
+ raise Pod::Informative, "#{k} 字段的值必须限定在可选值 [ #{selection.join(' / ')} ] 内".red
79
+ end
80
+ end
81
+ end
82
+
83
+ def respond_to_missing?(method, include_private = false)
84
+ config.respond_to?(method) || super
85
+ end
86
+
87
+ def method_missing(method, *args, &block)
88
+ if config.respond_to?(method)
89
+ config.send(method, *args)
90
+ elsif template_hash.keys.include?(method.to_s)
91
+ raise Pod::Informative, "#{method} 字段必须在配置文件 #{config_file} 中设置, 请执行 init 命令配置或手动修改配置文件".red
92
+ else
93
+ super
94
+ end
95
+ end
96
+ end
97
+
98
+ def self.config_hot_key
99
+ @config_hot_key ||= Config_Hot_Key.new
100
+ end
101
+
102
+ end
103
+