shopify-cli 0.9.0

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 (273) hide show
  1. checksums.yaml +7 -0
  2. data/.github/CODEOWNERS +1 -0
  3. data/.github/CODE_OF_CONDUCT.md +73 -0
  4. data/.github/CONTRIBUTING.md +51 -0
  5. data/.github/DESIGN.md +153 -0
  6. data/.github/ISSUE_TEMPLATE.md +38 -0
  7. data/.github/PULL_REQUEST_TEMPLATE.md +22 -0
  8. data/.github/probots.yml +3 -0
  9. data/.gitignore +19 -0
  10. data/.rubocop.yml +47 -0
  11. data/.ruby-version +1 -0
  12. data/.travis.yml +12 -0
  13. data/Gemfile +22 -0
  14. data/Gemfile.lock +77 -0
  15. data/LICENSE.md +7 -0
  16. data/README.md +13 -0
  17. data/Rakefile +101 -0
  18. data/SECURITY.md +59 -0
  19. data/Vagrantfile +17 -0
  20. data/bin/load_shopify.rb +20 -0
  21. data/bin/shopify +32 -0
  22. data/dev.yml +17 -0
  23. data/docs/Gemfile +5 -0
  24. data/docs/Gemfile.lock +248 -0
  25. data/docs/_config.yml +16 -0
  26. data/docs/_data/nav.yml +26 -0
  27. data/docs/_includes/footer.html +15 -0
  28. data/docs/_includes/head.html +19 -0
  29. data/docs/_includes/sidebar_nav.html +22 -0
  30. data/docs/_includes/toc.html +112 -0
  31. data/docs/_layouts/default.html +79 -0
  32. data/docs/app/node/commands/index.md +82 -0
  33. data/docs/app/node/index.md +35 -0
  34. data/docs/app/rails/commands/index.md +80 -0
  35. data/docs/app/rails/index.md +36 -0
  36. data/docs/core/index.md +70 -0
  37. data/docs/css/docs.css +157 -0
  38. data/docs/getting-started/index.md +61 -0
  39. data/docs/help/start-app/index.md +6 -0
  40. data/docs/images/header.png +0 -0
  41. data/docs/index.md +27 -0
  42. data/docs/installing-ruby.md +28 -0
  43. data/ext/shopify-cli/extconf.rb +27 -0
  44. data/install.sh +7 -0
  45. data/lib/docgen/class_template.md.erb +81 -0
  46. data/lib/docgen/index_template.md.erb +5 -0
  47. data/lib/docgen/markdown.rb +101 -0
  48. data/lib/graphql/admin_introspection.graphql +87 -0
  49. data/lib/graphql/all_organizations.graphql +19 -0
  50. data/lib/graphql/all_orgs_with_apps.graphql +30 -0
  51. data/lib/graphql/api_versions.graphql +6 -0
  52. data/lib/graphql/convert_dev_to_test_store.graphql +10 -0
  53. data/lib/graphql/create_app.graphql +20 -0
  54. data/lib/graphql/create_customer.graphql +9 -0
  55. data/lib/graphql/create_draft_order.graphql +8 -0
  56. data/lib/graphql/create_product.graphql +9 -0
  57. data/lib/graphql/extension_create.graphql +21 -0
  58. data/lib/graphql/extension_update_draft.graphql +18 -0
  59. data/lib/graphql/find_organization.graphql +17 -0
  60. data/lib/graphql/get_app_urls.graphql +6 -0
  61. data/lib/graphql/update_dashboard_urls.graphql +8 -0
  62. data/lib/project_types/extension/cli.rb +71 -0
  63. data/lib/project_types/extension/commands/build.rb +29 -0
  64. data/lib/project_types/extension/commands/create.rb +49 -0
  65. data/lib/project_types/extension/commands/extension_command.rb +22 -0
  66. data/lib/project_types/extension/commands/push.rb +69 -0
  67. data/lib/project_types/extension/commands/register.rb +78 -0
  68. data/lib/project_types/extension/commands/serve.rb +24 -0
  69. data/lib/project_types/extension/commands/tunnel.rb +69 -0
  70. data/lib/project_types/extension/extension_project.rb +85 -0
  71. data/lib/project_types/extension/extension_project_keys.rb +10 -0
  72. data/lib/project_types/extension/features/argo.rb +48 -0
  73. data/lib/project_types/extension/features/argo_dependencies.rb +28 -0
  74. data/lib/project_types/extension/features/argo_setup.rb +54 -0
  75. data/lib/project_types/extension/features/argo_setup_step.rb +31 -0
  76. data/lib/project_types/extension/features/argo_setup_steps.rb +53 -0
  77. data/lib/project_types/extension/features/tunnel_url.rb +20 -0
  78. data/lib/project_types/extension/forms/create.rb +52 -0
  79. data/lib/project_types/extension/forms/register.rb +48 -0
  80. data/lib/project_types/extension/messages/message_loading.rb +37 -0
  81. data/lib/project_types/extension/messages/messages.rb +126 -0
  82. data/lib/project_types/extension/models/app.rb +14 -0
  83. data/lib/project_types/extension/models/registration.rb +19 -0
  84. data/lib/project_types/extension/models/type.rb +76 -0
  85. data/lib/project_types/extension/models/types/checkout_post_purchase.rb +20 -0
  86. data/lib/project_types/extension/models/types/subscription_management.rb +20 -0
  87. data/lib/project_types/extension/models/validation_error.rb +17 -0
  88. data/lib/project_types/extension/models/version.rb +15 -0
  89. data/lib/project_types/extension/tasks/converters/registration_converter.rb +26 -0
  90. data/lib/project_types/extension/tasks/converters/validation_error_converter.rb +25 -0
  91. data/lib/project_types/extension/tasks/converters/version_converter.rb +28 -0
  92. data/lib/project_types/extension/tasks/create_extension.rb +31 -0
  93. data/lib/project_types/extension/tasks/get_apps.rb +34 -0
  94. data/lib/project_types/extension/tasks/update_draft.rb +29 -0
  95. data/lib/project_types/extension/tasks/user_errors.rb +45 -0
  96. data/lib/project_types/node/cli.rb +37 -0
  97. data/lib/project_types/node/commands/create.rb +117 -0
  98. data/lib/project_types/node/commands/deploy.rb +22 -0
  99. data/lib/project_types/node/commands/deploy/heroku.rb +91 -0
  100. data/lib/project_types/node/commands/generate.rb +51 -0
  101. data/lib/project_types/node/commands/generate/billing.rb +37 -0
  102. data/lib/project_types/node/commands/generate/page.rb +55 -0
  103. data/lib/project_types/node/commands/generate/webhook.rb +33 -0
  104. data/lib/project_types/node/commands/open.rb +16 -0
  105. data/lib/project_types/node/commands/populate.rb +23 -0
  106. data/lib/project_types/node/commands/populate/customer.rb +31 -0
  107. data/lib/project_types/node/commands/populate/draft_order.rb +28 -0
  108. data/lib/project_types/node/commands/populate/product.rb +30 -0
  109. data/lib/project_types/node/commands/serve.rb +45 -0
  110. data/lib/project_types/node/commands/tunnel.rb +39 -0
  111. data/lib/project_types/node/forms/create.rb +87 -0
  112. data/lib/project_types/node/messages/messages.rb +260 -0
  113. data/lib/project_types/rails/cli.rb +41 -0
  114. data/lib/project_types/rails/commands/create.rb +126 -0
  115. data/lib/project_types/rails/commands/deploy.rb +22 -0
  116. data/lib/project_types/rails/commands/deploy/heroku.rb +113 -0
  117. data/lib/project_types/rails/commands/generate.rb +49 -0
  118. data/lib/project_types/rails/commands/generate/webhook.rb +39 -0
  119. data/lib/project_types/rails/commands/open.rb +16 -0
  120. data/lib/project_types/rails/commands/populate.rb +23 -0
  121. data/lib/project_types/rails/commands/populate/customer.rb +31 -0
  122. data/lib/project_types/rails/commands/populate/draft_order.rb +28 -0
  123. data/lib/project_types/rails/commands/populate/product.rb +30 -0
  124. data/lib/project_types/rails/commands/serve.rb +47 -0
  125. data/lib/project_types/rails/commands/tunnel.rb +39 -0
  126. data/lib/project_types/rails/forms/create.rb +116 -0
  127. data/lib/project_types/rails/gem.rb +56 -0
  128. data/lib/project_types/rails/messages/messages.rb +283 -0
  129. data/lib/project_types/rails/ruby.rb +17 -0
  130. data/lib/project_types/script/cli.rb +76 -0
  131. data/lib/project_types/script/commands/create.rb +45 -0
  132. data/lib/project_types/script/commands/disable.rb +36 -0
  133. data/lib/project_types/script/commands/enable.rb +46 -0
  134. data/lib/project_types/script/commands/push.rb +39 -0
  135. data/lib/project_types/script/config/extension_points.yml +18 -0
  136. data/lib/project_types/script/errors.rb +16 -0
  137. data/lib/project_types/script/forms/create.rb +29 -0
  138. data/lib/project_types/script/forms/enable.rb +24 -0
  139. data/lib/project_types/script/forms/push.rb +19 -0
  140. data/lib/project_types/script/forms/script_form.rb +66 -0
  141. data/lib/project_types/script/graphql/app_script_update_or_create.graphql +27 -0
  142. data/lib/project_types/script/graphql/script_service_proxy.graphql +8 -0
  143. data/lib/project_types/script/graphql/shop_script_delete.graphql +14 -0
  144. data/lib/project_types/script/graphql/shop_script_update_or_create.graphql +28 -0
  145. data/lib/project_types/script/layers/application/build_script.rb +43 -0
  146. data/lib/project_types/script/layers/application/create_script.rb +47 -0
  147. data/lib/project_types/script/layers/application/disable_script.rb +19 -0
  148. data/lib/project_types/script/layers/application/enable_script.rb +21 -0
  149. data/lib/project_types/script/layers/application/extension_points.rb +17 -0
  150. data/lib/project_types/script/layers/application/project_dependencies.rb +34 -0
  151. data/lib/project_types/script/layers/application/push_script.rb +30 -0
  152. data/lib/project_types/script/layers/domain/errors.rb +25 -0
  153. data/lib/project_types/script/layers/domain/extension_point.rb +29 -0
  154. data/lib/project_types/script/layers/domain/push_package.rb +29 -0
  155. data/lib/project_types/script/layers/domain/script.rb +18 -0
  156. data/lib/project_types/script/layers/infrastructure/assemblyscript_dependency_manager.rb +73 -0
  157. data/lib/project_types/script/layers/infrastructure/assemblyscript_tsconfig.rb +38 -0
  158. data/lib/project_types/script/layers/infrastructure/assemblyscript_wasm_builder.rb +39 -0
  159. data/lib/project_types/script/layers/infrastructure/dependency_manager.rb +36 -0
  160. data/lib/project_types/script/layers/infrastructure/errors.rb +38 -0
  161. data/lib/project_types/script/layers/infrastructure/extension_point_repository.rb +31 -0
  162. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +47 -0
  163. data/lib/project_types/script/layers/infrastructure/script_builder.rb +34 -0
  164. data/lib/project_types/script/layers/infrastructure/script_repository.rb +89 -0
  165. data/lib/project_types/script/layers/infrastructure/script_service.rb +165 -0
  166. data/lib/project_types/script/layers/infrastructure/test_suite_repository.rb +59 -0
  167. data/lib/project_types/script/messages/messages.rb +204 -0
  168. data/lib/project_types/script/script_project.rb +37 -0
  169. data/lib/project_types/script/templates/ts/as-pect.config.js +21 -0
  170. data/lib/project_types/script/ui/error_handler.rb +136 -0
  171. data/lib/project_types/script/ui/strict_spinner.rb +22 -0
  172. data/lib/rubygems_plugin.rb +18 -0
  173. data/lib/shopify-cli/admin_api.rb +99 -0
  174. data/lib/shopify-cli/admin_api/populate_resource_command.rb +165 -0
  175. data/lib/shopify-cli/admin_api/schema.rb +32 -0
  176. data/lib/shopify-cli/api.rb +104 -0
  177. data/lib/shopify-cli/command.rb +67 -0
  178. data/lib/shopify-cli/commands.rb +28 -0
  179. data/lib/shopify-cli/commands/connect.rb +108 -0
  180. data/lib/shopify-cli/commands/create.rb +50 -0
  181. data/lib/shopify-cli/commands/help.rb +79 -0
  182. data/lib/shopify-cli/commands/logout.rb +23 -0
  183. data/lib/shopify-cli/commands/system.rb +135 -0
  184. data/lib/shopify-cli/commands/version.rb +15 -0
  185. data/lib/shopify-cli/context.rb +372 -0
  186. data/lib/shopify-cli/core.rb +9 -0
  187. data/lib/shopify-cli/core/entry_point.rb +40 -0
  188. data/lib/shopify-cli/core/executor.rb +21 -0
  189. data/lib/shopify-cli/core/help_resolver.rb +20 -0
  190. data/lib/shopify-cli/core/monorail.rb +118 -0
  191. data/lib/shopify-cli/db.rb +114 -0
  192. data/lib/shopify-cli/form.rb +40 -0
  193. data/lib/shopify-cli/git.rb +141 -0
  194. data/lib/shopify-cli/helpers.rb +5 -0
  195. data/lib/shopify-cli/helpers/haikunator.rb +92 -0
  196. data/lib/shopify-cli/heroku.rb +97 -0
  197. data/lib/shopify-cli/js_deps.rb +110 -0
  198. data/lib/shopify-cli/js_system.rb +98 -0
  199. data/lib/shopify-cli/messages/messages.rb +287 -0
  200. data/lib/shopify-cli/oauth.rb +192 -0
  201. data/lib/shopify-cli/oauth/servlet.rb +61 -0
  202. data/lib/shopify-cli/options.rb +40 -0
  203. data/lib/shopify-cli/packager.rb +116 -0
  204. data/lib/shopify-cli/partners_api.rb +114 -0
  205. data/lib/shopify-cli/partners_api/organizations.rb +32 -0
  206. data/lib/shopify-cli/process_supervision.rb +187 -0
  207. data/lib/shopify-cli/project.rb +191 -0
  208. data/lib/shopify-cli/project_type.rb +83 -0
  209. data/lib/shopify-cli/resources.rb +5 -0
  210. data/lib/shopify-cli/resources/env_file.rb +96 -0
  211. data/lib/shopify-cli/sub_command.rb +15 -0
  212. data/lib/shopify-cli/task.rb +10 -0
  213. data/lib/shopify-cli/tasks.rb +32 -0
  214. data/lib/shopify-cli/tasks/create_api_client.rb +29 -0
  215. data/lib/shopify-cli/tasks/ensure_dev_store.rb +41 -0
  216. data/lib/shopify-cli/tasks/ensure_env.rb +31 -0
  217. data/lib/shopify-cli/tasks/ensure_loopback_url.rb +20 -0
  218. data/lib/shopify-cli/tasks/update_dashboard_urls.rb +44 -0
  219. data/lib/shopify-cli/tunnel.rb +154 -0
  220. data/lib/shopify-cli/version.rb +3 -0
  221. data/lib/shopify_cli.rb +132 -0
  222. data/shopify-cli.gemspec +40 -0
  223. data/shopify.fish +12 -0
  224. data/shopify.sh +11 -0
  225. data/vendor/deps/cli-kit/REVISION +1 -0
  226. data/vendor/deps/cli-kit/lib/cli/kit.rb +60 -0
  227. data/vendor/deps/cli-kit/lib/cli/kit/autocall.rb +21 -0
  228. data/vendor/deps/cli-kit/lib/cli/kit/base_command.rb +49 -0
  229. data/vendor/deps/cli-kit/lib/cli/kit/command_registry.rb +94 -0
  230. data/vendor/deps/cli-kit/lib/cli/kit/config.rb +133 -0
  231. data/vendor/deps/cli-kit/lib/cli/kit/error_handler.rb +115 -0
  232. data/vendor/deps/cli-kit/lib/cli/kit/executor.rb +81 -0
  233. data/vendor/deps/cli-kit/lib/cli/kit/ini.rb +102 -0
  234. data/vendor/deps/cli-kit/lib/cli/kit/levenshtein.rb +82 -0
  235. data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +76 -0
  236. data/vendor/deps/cli-kit/lib/cli/kit/resolver.rb +60 -0
  237. data/vendor/deps/cli-kit/lib/cli/kit/ruby_backports/enumerable.rb +6 -0
  238. data/vendor/deps/cli-kit/lib/cli/kit/support.rb +9 -0
  239. data/vendor/deps/cli-kit/lib/cli/kit/support/test_helper.rb +244 -0
  240. data/vendor/deps/cli-kit/lib/cli/kit/system.rb +207 -0
  241. data/vendor/deps/cli-kit/lib/cli/kit/util.rb +189 -0
  242. data/vendor/deps/cli-kit/lib/cli/kit/version.rb +5 -0
  243. data/vendor/deps/cli-ui/REVISION +1 -0
  244. data/vendor/deps/cli-ui/lib/cli/ui.rb +187 -0
  245. data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +153 -0
  246. data/vendor/deps/cli-ui/lib/cli/ui/box.rb +15 -0
  247. data/vendor/deps/cli-ui/lib/cli/ui/color.rb +79 -0
  248. data/vendor/deps/cli-ui/lib/cli/ui/formatter.rb +179 -0
  249. data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +310 -0
  250. data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +78 -0
  251. data/vendor/deps/cli-ui/lib/cli/ui/progress.rb +88 -0
  252. data/vendor/deps/cli-ui/lib/cli/ui/prompt.rb +248 -0
  253. data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +472 -0
  254. data/vendor/deps/cli-ui/lib/cli/ui/prompt/options_handler.rb +24 -0
  255. data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +48 -0
  256. data/vendor/deps/cli-ui/lib/cli/ui/spinner/async.rb +40 -0
  257. data/vendor/deps/cli-ui/lib/cli/ui/spinner/spin_group.rb +241 -0
  258. data/vendor/deps/cli-ui/lib/cli/ui/stdout_router.rb +227 -0
  259. data/vendor/deps/cli-ui/lib/cli/ui/terminal.rb +36 -0
  260. data/vendor/deps/cli-ui/lib/cli/ui/truncater.rb +102 -0
  261. data/vendor/deps/cli-ui/lib/cli/ui/version.rb +5 -0
  262. data/vendor/deps/smart_properties/REVISION +1 -0
  263. data/vendor/deps/smart_properties/lib/smart_properties.rb +174 -0
  264. data/vendor/deps/smart_properties/lib/smart_properties/errors.rb +114 -0
  265. data/vendor/deps/smart_properties/lib/smart_properties/property.rb +162 -0
  266. data/vendor/deps/smart_properties/lib/smart_properties/property_collection.rb +83 -0
  267. data/vendor/deps/smart_properties/lib/smart_properties/validations.rb +8 -0
  268. data/vendor/deps/smart_properties/lib/smart_properties/validations/ancestor.rb +27 -0
  269. data/vendor/deps/smart_properties/lib/smart_properties/version.rb +3 -0
  270. data/vendor/lib/semantic/LICENSE +20 -0
  271. data/vendor/lib/semantic/semantic.rb +4 -0
  272. data/vendor/lib/semantic/version.rb +180 -0
  273. metadata +374 -0
@@ -0,0 +1,189 @@
1
+ module CLI
2
+ module Kit
3
+ module Util
4
+ class << self
5
+ def snake_case(camel_case, seperator = "_")
6
+ camel_case.to_s # MyCoolThing::MyAPIModule
7
+ .gsub(/::/, '/') # MyCoolThing/MyAPIModule
8
+ .gsub(/([A-Z]+)([A-Z][a-z])/, "\\1#{seperator}\\2") # MyCoolThing::MyAPI_Module
9
+ .gsub(/([a-z\d])([A-Z])/, "\\1#{seperator}\\2") # My_Cool_Thing::My_API_Module
10
+ .downcase # my_cool_thing/my_api_module
11
+ end
12
+
13
+ def dash_case(camel_case)
14
+ snake_case(camel_case, '-')
15
+ end
16
+
17
+ # The following methods is taken from activesupport
18
+ # All credit for this method goes to the original authors.
19
+ # https://github.com/rails/rails/blob/d66e7835bea9505f7003e5038aa19b6ea95ceea1/activesupport/lib/active_support/core_ext/string/strip.rb
20
+ #
21
+ # Copyright (c) 2005-2018 David Heinemeier Hansson
22
+ #
23
+ # Permission is hereby granted, free of charge, to any person obtaining
24
+ # a copy of this software and associated documentation files (the
25
+ # "Software"), to deal in the Software without restriction, including
26
+ # without limitation the rights to use, copy, modify, merge, publish,
27
+ # distribute, sublicense, and/or sell copies of the Software, and to
28
+ # permit persons to whom the Software is furnished to do so, subject to
29
+ # the following conditions:
30
+ #
31
+ # The above copyright notice and this permission notice shall be
32
+ # included in all copies or substantial portions of the Software.
33
+ #
34
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
35
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
36
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
37
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
38
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
39
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
40
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41
+ #
42
+ # Strips indentation by removing the amount of leading whitespace in the least indented
43
+ # non-empty line in the whole string
44
+ #
45
+ def strip_heredoc(str)
46
+ str.gsub(/^#{str.scan(/^[ \t]*(?=\S)/).min}/, "".freeze)
47
+ end
48
+
49
+ # Joins an array with commas and "and", using the Oxford comma.
50
+ def english_join(array)
51
+ return "" if array.nil?
52
+ return array.join(" and ") if array.length < 3
53
+
54
+ "#{array[0..-2].join(', ')}, and #{array[-1]}"
55
+ end
56
+
57
+ # Execute a block within the context of a variable enviroment
58
+ #
59
+ def with_environment(environment, value)
60
+ return yield unless environment
61
+
62
+ old_env = ENV[environment]
63
+ begin
64
+ ENV[environment] = value
65
+ yield
66
+ ensure
67
+ old_env ? ENV[environment] = old_env : ENV.delete(environment)
68
+ end
69
+ end
70
+
71
+ # Converts an integer representing bytes into a human readable format
72
+ #
73
+ def to_filesize(bytes, precision: 2, space: false)
74
+ to_si_scale(bytes, 'B', precision: precision, space: space, factor: 1024)
75
+ end
76
+
77
+ # Converts a number to a human readable format on the SI scale
78
+ #
79
+ def to_si_scale(number, unit = '', factor: 1000, precision: 2, space: false)
80
+ raise ArgumentError, "factor should only be 1000 or 1024" unless [1000, 1024].include?(factor)
81
+
82
+ small_scale = %w(m µ n p f a z y)
83
+ big_scale = %w(k M G T P E Z Y)
84
+ negative = number < 0
85
+ number = number.abs.to_f
86
+
87
+ if number == 0 || number.between?(1, factor)
88
+ prefix = ""
89
+ scale = 0
90
+ else
91
+ scale = Math.log(number, factor).floor
92
+ if number < 1
93
+ index = [-scale - 1, small_scale.length].min
94
+ scale = -(index + 1)
95
+ prefix = small_scale[index]
96
+ else
97
+ index = [scale - 1, big_scale.length].min
98
+ scale = index + 1
99
+ prefix = big_scale[index]
100
+ end
101
+ end
102
+
103
+ divider = (factor**scale)
104
+ fnum = (number / divider).round(precision)
105
+
106
+ # Trim useless decimal
107
+ fnum = fnum.to_i if (fnum.to_i.to_f * divider) == number
108
+
109
+ fnum = -fnum if negative
110
+ prefix = " " + prefix if space
111
+
112
+ "#{fnum}#{prefix}#{unit}"
113
+ end
114
+
115
+ # Dir.chdir, when invoked in block form, complains when we call chdir
116
+ # again recursively. There's no apparent good reason for this, so we
117
+ # simply implement our own block form of Dir.chdir here.
118
+ def with_dir(dir)
119
+ prev = Dir.pwd
120
+ Dir.chdir(dir)
121
+ yield
122
+ ensure
123
+ Dir.chdir(prev)
124
+ end
125
+
126
+ def with_tmp_dir
127
+ require 'fileutils'
128
+ dir = Dir.mktmpdir
129
+ with_dir(dir) do
130
+ yield(dir)
131
+ end
132
+ ensure
133
+ FileUtils.remove_entry(dir)
134
+ end
135
+
136
+ # Standard way of checking for CI / Tests
137
+ def testing?
138
+ ci? || ENV['TEST']
139
+ end
140
+
141
+ # Set only in IntegrationTest#session; indicates that the process was
142
+ # called by `session.execute` from an IntegrationTest subclass.
143
+ def integration_test_session?
144
+ ENV['INTEGRATION_TEST_SESSION']
145
+ end
146
+
147
+ # Standard way of checking for CI
148
+ def ci?
149
+ ENV['CI']
150
+ end
151
+
152
+ # Must call retry_after on the result in order to execute the block
153
+ #
154
+ # Example usage:
155
+ #
156
+ # CLI::Kit::Util.begin do
157
+ # might_raise_if_costly_prep_not_done()
158
+ # end.retry_after(ExpectedError) do
159
+ # costly_prep()
160
+ # end
161
+ def begin(&block_that_might_raise)
162
+ Retrier.new(block_that_might_raise)
163
+ end
164
+ end
165
+
166
+ class Retrier
167
+ def initialize(block_that_might_raise)
168
+ @block_that_might_raise = block_that_might_raise
169
+ end
170
+
171
+ def retry_after(exception = StandardError, retries: 1, &before_retry)
172
+ @block_that_might_raise.call
173
+ rescue exception => e
174
+ raise if (retries -= 1) < 0
175
+ if before_retry
176
+ if before_retry.arity == 0
177
+ yield
178
+ else
179
+ yield e
180
+ end
181
+ end
182
+ retry
183
+ end
184
+ end
185
+
186
+ private_constant :Retrier
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,5 @@
1
+ module CLI
2
+ module Kit
3
+ VERSION = "3.3.0"
4
+ end
5
+ end
@@ -0,0 +1 @@
1
+ 35e1b188f19b2ba0ab85bbf48ab983b1f72a361b
@@ -0,0 +1,187 @@
1
+ module CLI
2
+ module UI
3
+ autoload :ANSI, 'cli/ui/ansi'
4
+ autoload :Glyph, 'cli/ui/glyph'
5
+ autoload :Color, 'cli/ui/color'
6
+ autoload :Box, 'cli/ui/box'
7
+ autoload :Frame, 'cli/ui/frame'
8
+ autoload :Progress, 'cli/ui/progress'
9
+ autoload :Prompt, 'cli/ui/prompt'
10
+ autoload :Terminal, 'cli/ui/terminal'
11
+ autoload :Truncater, 'cli/ui/truncater'
12
+ autoload :Formatter, 'cli/ui/formatter'
13
+ autoload :Spinner, 'cli/ui/spinner'
14
+
15
+ # Convenience accessor to +CLI::UI::Spinner::SpinGroup+
16
+ SpinGroup = Spinner::SpinGroup
17
+
18
+ # Glyph resolution using +CLI::UI::Glyph.lookup+
19
+ # Look at the method signature for +Glyph.lookup+ for more details
20
+ #
21
+ # ==== Attributes
22
+ #
23
+ # * +handle+ - handle of the glyph to resolve
24
+ #
25
+ def self.glyph(handle)
26
+ CLI::UI::Glyph.lookup(handle)
27
+ end
28
+
29
+ # Color resolution using +CLI::UI::Color.lookup+
30
+ # Will lookup using +Color.lookup+ if a symbol, otherwise we assume it is a valid color and return it
31
+ #
32
+ # ==== Attributes
33
+ #
34
+ # * +input+ - color to resolve
35
+ #
36
+ def self.resolve_color(input)
37
+ case input
38
+ when Symbol
39
+ CLI::UI::Color.lookup(input)
40
+ else
41
+ input
42
+ end
43
+ end
44
+
45
+ # Conviencence Method for +CLI::UI::Prompt.confirm+
46
+ #
47
+ # ==== Attributes
48
+ #
49
+ # * +question+ - question to confirm
50
+ #
51
+ def self.confirm(question, **kwargs)
52
+ CLI::UI::Prompt.confirm(question, **kwargs)
53
+ end
54
+
55
+ # Conviencence Method for +CLI::UI::Prompt.ask+
56
+ #
57
+ # ==== Attributes
58
+ #
59
+ # * +question+ - question to ask
60
+ # * +kwargs+ - arugments for +Prompt.ask+
61
+ #
62
+ def self.ask(question, **kwargs)
63
+ CLI::UI::Prompt.ask(question, **kwargs)
64
+ end
65
+
66
+ # Conviencence Method to resolve text using +CLI::UI::Formatter.format+
67
+ # Check +CLI::UI::Formatter::SGR_MAP+ for available formatting options
68
+ #
69
+ # ==== Attributes
70
+ #
71
+ # * +input+ - input to format
72
+ # * +truncate_to+ - number of characters to truncate the string to (or nil)
73
+ #
74
+ def self.resolve_text(input, truncate_to: nil)
75
+ return input if input.nil?
76
+ formatted = CLI::UI::Formatter.new(input).format
77
+ return formatted unless truncate_to
78
+ return CLI::UI::Truncater.call(formatted, truncate_to)
79
+ end
80
+
81
+ # Conviencence Method to format text using +CLI::UI::Formatter.format+
82
+ # Check +CLI::UI::Formatter::SGR_MAP+ for available formatting options
83
+ #
84
+ # https://user-images.githubusercontent.com/3074765/33799827-6d0721a2-dd01-11e7-9ab5-c3d455264afe.png
85
+ # https://user-images.githubusercontent.com/3074765/33799847-9ec03fd0-dd01-11e7-93f7-5f5cc540e61e.png
86
+ #
87
+ # ==== Attributes
88
+ #
89
+ # * +input+ - input to format
90
+ #
91
+ # ==== Options
92
+ #
93
+ # * +enable_color+ - should color be used? default to true unless output is redirected.
94
+ #
95
+ def self.fmt(input, enable_color: enable_color?)
96
+ CLI::UI::Formatter.new(input).format(enable_color: enable_color)
97
+ end
98
+
99
+ # Conviencence Method for +CLI::UI::Frame.open+
100
+ #
101
+ # ==== Attributes
102
+ #
103
+ # * +args+ - arguments for +Frame.open+
104
+ # * +block+ - block for +Frame.open+
105
+ #
106
+ def self.frame(*args, &block)
107
+ CLI::UI::Frame.open(*args, &block)
108
+ end
109
+
110
+ # Conviencence Method for +CLI::UI::Spinner.spin+
111
+ #
112
+ # ==== Attributes
113
+ #
114
+ # * +args+ - arguments for +Spinner.open+
115
+ # * +block+ - block for +Spinner.open+
116
+ #
117
+ def self.spinner(*args, &block)
118
+ CLI::UI::Spinner.spin(*args, &block)
119
+ end
120
+
121
+ # Conviencence Method to override frame color using +CLI::UI::Frame.with_frame_color+
122
+ #
123
+ # ==== Attributes
124
+ #
125
+ # * +color+ - color to override to
126
+ # * +block+ - block for +Frame.with_frame_color_override+
127
+ #
128
+ def self.with_frame_color(color, &block)
129
+ CLI::UI::Frame.with_frame_color_override(color, &block)
130
+ end
131
+
132
+ # Duplicate output to a file path
133
+ #
134
+ # ==== Attributes
135
+ #
136
+ # * +path+ - path to duplicate output to
137
+ #
138
+ def self.log_output_to(path)
139
+ if CLI::UI::StdoutRouter.duplicate_output_to
140
+ raise "multiple logs not allowed"
141
+ end
142
+ CLI::UI::StdoutRouter.duplicate_output_to = File.open(path, 'w')
143
+ yield
144
+ ensure
145
+ if file_descriptor = CLI::UI::StdoutRouter.duplicate_output_to
146
+ file_descriptor.close
147
+ CLI::UI::StdoutRouter.duplicate_output_to = nil
148
+ end
149
+ end
150
+
151
+ # Disable all framing within a block
152
+ #
153
+ # ==== Attributes
154
+ #
155
+ # * +block+ - block in which to disable frames
156
+ #
157
+ def self.raw
158
+ prev = Thread.current[:no_cliui_frame_inset]
159
+ Thread.current[:no_cliui_frame_inset] = true
160
+ yield
161
+ ensure
162
+ Thread.current[:no_cliui_frame_inset] = prev
163
+ end
164
+
165
+ # Check whether colour is enabled in Formatter output. By default, colour
166
+ # is enabled when STDOUT is a TTY; that is, when output has not been
167
+ # redirected to another program or to a file.
168
+ #
169
+ def self.enable_color?
170
+ @enable_color
171
+ end
172
+
173
+ # Turn colour output in Formatter on or off.
174
+ #
175
+ # ==== Attributes
176
+ #
177
+ # * +bool+ - true or false; enable or disable colour.
178
+ #
179
+ def self.enable_color=(bool)
180
+ @enable_color = !!bool
181
+ end
182
+
183
+ self.enable_color = $stdout.tty?
184
+ end
185
+ end
186
+
187
+ require 'cli/ui/stdout_router'
@@ -0,0 +1,153 @@
1
+ require 'cli/ui'
2
+
3
+ module CLI
4
+ module UI
5
+ module ANSI
6
+ ESC = "\x1b"
7
+
8
+ # ANSI escape sequences (like \x1b[31m) have zero width.
9
+ # when calculating the padding width, we must exclude them.
10
+ # This also implements a basic version of utf8 character width calculation like
11
+ # we could get for real from something like utf8proc.
12
+ #
13
+ def self.printing_width(str)
14
+ zwj = false
15
+ strip_codes(str).codepoints.reduce(0) do |acc, cp|
16
+ if zwj
17
+ zwj = false
18
+ next acc
19
+ end
20
+ case cp
21
+ when 0x200d # zero-width joiner
22
+ zwj = true
23
+ acc
24
+ else
25
+ acc + 1
26
+ end
27
+ end
28
+ end
29
+
30
+ # Strips ANSI codes from a str
31
+ #
32
+ # ==== Attributes
33
+ #
34
+ # - +str+ - The string from which to strip codes
35
+ #
36
+ def self.strip_codes(str)
37
+ str.gsub(/\x1b\[[\d;]+[A-z]|\r/, '')
38
+ end
39
+
40
+ # Returns an ANSI control sequence
41
+ #
42
+ # ==== Attributes
43
+ #
44
+ # - +args+ - Argument to pass to the ANSI control sequence
45
+ # - +cmd+ - ANSI control sequence Command
46
+ #
47
+ def self.control(args, cmd)
48
+ ESC + "[" + args + cmd
49
+ end
50
+
51
+ # https://en.wikipedia.org/wiki/ANSI_escape_code#graphics
52
+ def self.sgr(params)
53
+ control(params.to_s, 'm')
54
+ end
55
+
56
+ # Cursor Movement
57
+
58
+ # Move the cursor up n lines
59
+ #
60
+ # ==== Attributes
61
+ #
62
+ # * +n+ - number of lines by which to move the cursor up
63
+ #
64
+ def self.cursor_up(n = 1)
65
+ return '' if n.zero?
66
+ control(n.to_s, 'A')
67
+ end
68
+
69
+ # Move the cursor down n lines
70
+ #
71
+ # ==== Attributes
72
+ #
73
+ # * +n+ - number of lines by which to move the cursor down
74
+ #
75
+ def self.cursor_down(n = 1)
76
+ return '' if n.zero?
77
+ control(n.to_s, 'B')
78
+ end
79
+
80
+ # Move the cursor forward n columns
81
+ #
82
+ # ==== Attributes
83
+ #
84
+ # * +n+ - number of columns by which to move the cursor forward
85
+ #
86
+ def self.cursor_forward(n = 1)
87
+ return '' if n.zero?
88
+ control(n.to_s, 'C')
89
+ end
90
+
91
+ # Move the cursor back n columns
92
+ #
93
+ # ==== Attributes
94
+ #
95
+ # * +n+ - number of columns by which to move the cursor back
96
+ #
97
+ def self.cursor_back(n = 1)
98
+ return '' if n.zero?
99
+ control(n.to_s, 'D')
100
+ end
101
+
102
+ # Move the cursor to a specific column
103
+ #
104
+ # ==== Attributes
105
+ #
106
+ # * +n+ - The column to move to
107
+ #
108
+ def self.cursor_horizontal_absolute(n = 1)
109
+ control(n.to_s, 'G')
110
+ end
111
+
112
+ # Show the cursor
113
+ #
114
+ def self.show_cursor
115
+ control('', "?25h")
116
+ end
117
+
118
+ # Hide the cursor
119
+ #
120
+ def self.hide_cursor
121
+ control('', "?25l")
122
+ end
123
+
124
+ # Save the cursor position
125
+ #
126
+ def self.cursor_save
127
+ control('', 's')
128
+ end
129
+
130
+ # Restore the saved cursor position
131
+ #
132
+ def self.cursor_restore
133
+ control('', 'u')
134
+ end
135
+
136
+ # Move to the next line
137
+ #
138
+ def self.next_line
139
+ cursor_down + control('1', 'G')
140
+ end
141
+
142
+ # Move to the previous line
143
+ #
144
+ def self.previous_line
145
+ cursor_up + control('1', 'G')
146
+ end
147
+
148
+ def self.clear_to_end_of_line
149
+ control('', 'K')
150
+ end
151
+ end
152
+ end
153
+ end