shopify-cli 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/CODEOWNERS +1 -0
- data/.github/CODE_OF_CONDUCT.md +73 -0
- data/.github/CONTRIBUTING.md +51 -0
- data/.github/DESIGN.md +153 -0
- data/.github/ISSUE_TEMPLATE.md +38 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +22 -0
- data/.github/probots.yml +3 -0
- data/.gitignore +19 -0
- data/.rubocop.yml +47 -0
- data/.ruby-version +1 -0
- data/.travis.yml +12 -0
- data/Gemfile +22 -0
- data/Gemfile.lock +77 -0
- data/LICENSE.md +7 -0
- data/README.md +13 -0
- data/Rakefile +101 -0
- data/SECURITY.md +59 -0
- data/Vagrantfile +17 -0
- data/bin/load_shopify.rb +20 -0
- data/bin/shopify +32 -0
- data/dev.yml +17 -0
- data/docs/Gemfile +5 -0
- data/docs/Gemfile.lock +248 -0
- data/docs/_config.yml +16 -0
- data/docs/_data/nav.yml +26 -0
- data/docs/_includes/footer.html +15 -0
- data/docs/_includes/head.html +19 -0
- data/docs/_includes/sidebar_nav.html +22 -0
- data/docs/_includes/toc.html +112 -0
- data/docs/_layouts/default.html +79 -0
- data/docs/app/node/commands/index.md +82 -0
- data/docs/app/node/index.md +35 -0
- data/docs/app/rails/commands/index.md +80 -0
- data/docs/app/rails/index.md +36 -0
- data/docs/core/index.md +70 -0
- data/docs/css/docs.css +157 -0
- data/docs/getting-started/index.md +61 -0
- data/docs/help/start-app/index.md +6 -0
- data/docs/images/header.png +0 -0
- data/docs/index.md +27 -0
- data/docs/installing-ruby.md +28 -0
- data/ext/shopify-cli/extconf.rb +27 -0
- data/install.sh +7 -0
- data/lib/docgen/class_template.md.erb +81 -0
- data/lib/docgen/index_template.md.erb +5 -0
- data/lib/docgen/markdown.rb +101 -0
- data/lib/graphql/admin_introspection.graphql +87 -0
- data/lib/graphql/all_organizations.graphql +19 -0
- data/lib/graphql/all_orgs_with_apps.graphql +30 -0
- data/lib/graphql/api_versions.graphql +6 -0
- data/lib/graphql/convert_dev_to_test_store.graphql +10 -0
- data/lib/graphql/create_app.graphql +20 -0
- data/lib/graphql/create_customer.graphql +9 -0
- data/lib/graphql/create_draft_order.graphql +8 -0
- data/lib/graphql/create_product.graphql +9 -0
- data/lib/graphql/extension_create.graphql +21 -0
- data/lib/graphql/extension_update_draft.graphql +18 -0
- data/lib/graphql/find_organization.graphql +17 -0
- data/lib/graphql/get_app_urls.graphql +6 -0
- data/lib/graphql/update_dashboard_urls.graphql +8 -0
- data/lib/project_types/extension/cli.rb +71 -0
- data/lib/project_types/extension/commands/build.rb +29 -0
- data/lib/project_types/extension/commands/create.rb +49 -0
- data/lib/project_types/extension/commands/extension_command.rb +22 -0
- data/lib/project_types/extension/commands/push.rb +69 -0
- data/lib/project_types/extension/commands/register.rb +78 -0
- data/lib/project_types/extension/commands/serve.rb +24 -0
- data/lib/project_types/extension/commands/tunnel.rb +69 -0
- data/lib/project_types/extension/extension_project.rb +85 -0
- data/lib/project_types/extension/extension_project_keys.rb +10 -0
- data/lib/project_types/extension/features/argo.rb +48 -0
- data/lib/project_types/extension/features/argo_dependencies.rb +28 -0
- data/lib/project_types/extension/features/argo_setup.rb +54 -0
- data/lib/project_types/extension/features/argo_setup_step.rb +31 -0
- data/lib/project_types/extension/features/argo_setup_steps.rb +53 -0
- data/lib/project_types/extension/features/tunnel_url.rb +20 -0
- data/lib/project_types/extension/forms/create.rb +52 -0
- data/lib/project_types/extension/forms/register.rb +48 -0
- data/lib/project_types/extension/messages/message_loading.rb +37 -0
- data/lib/project_types/extension/messages/messages.rb +126 -0
- data/lib/project_types/extension/models/app.rb +14 -0
- data/lib/project_types/extension/models/registration.rb +19 -0
- data/lib/project_types/extension/models/type.rb +76 -0
- data/lib/project_types/extension/models/types/checkout_post_purchase.rb +20 -0
- data/lib/project_types/extension/models/types/subscription_management.rb +20 -0
- data/lib/project_types/extension/models/validation_error.rb +17 -0
- data/lib/project_types/extension/models/version.rb +15 -0
- data/lib/project_types/extension/tasks/converters/registration_converter.rb +26 -0
- data/lib/project_types/extension/tasks/converters/validation_error_converter.rb +25 -0
- data/lib/project_types/extension/tasks/converters/version_converter.rb +28 -0
- data/lib/project_types/extension/tasks/create_extension.rb +31 -0
- data/lib/project_types/extension/tasks/get_apps.rb +34 -0
- data/lib/project_types/extension/tasks/update_draft.rb +29 -0
- data/lib/project_types/extension/tasks/user_errors.rb +45 -0
- data/lib/project_types/node/cli.rb +37 -0
- data/lib/project_types/node/commands/create.rb +117 -0
- data/lib/project_types/node/commands/deploy.rb +22 -0
- data/lib/project_types/node/commands/deploy/heroku.rb +91 -0
- data/lib/project_types/node/commands/generate.rb +51 -0
- data/lib/project_types/node/commands/generate/billing.rb +37 -0
- data/lib/project_types/node/commands/generate/page.rb +55 -0
- data/lib/project_types/node/commands/generate/webhook.rb +33 -0
- data/lib/project_types/node/commands/open.rb +16 -0
- data/lib/project_types/node/commands/populate.rb +23 -0
- data/lib/project_types/node/commands/populate/customer.rb +31 -0
- data/lib/project_types/node/commands/populate/draft_order.rb +28 -0
- data/lib/project_types/node/commands/populate/product.rb +30 -0
- data/lib/project_types/node/commands/serve.rb +45 -0
- data/lib/project_types/node/commands/tunnel.rb +39 -0
- data/lib/project_types/node/forms/create.rb +87 -0
- data/lib/project_types/node/messages/messages.rb +260 -0
- data/lib/project_types/rails/cli.rb +41 -0
- data/lib/project_types/rails/commands/create.rb +126 -0
- data/lib/project_types/rails/commands/deploy.rb +22 -0
- data/lib/project_types/rails/commands/deploy/heroku.rb +113 -0
- data/lib/project_types/rails/commands/generate.rb +49 -0
- data/lib/project_types/rails/commands/generate/webhook.rb +39 -0
- data/lib/project_types/rails/commands/open.rb +16 -0
- data/lib/project_types/rails/commands/populate.rb +23 -0
- data/lib/project_types/rails/commands/populate/customer.rb +31 -0
- data/lib/project_types/rails/commands/populate/draft_order.rb +28 -0
- data/lib/project_types/rails/commands/populate/product.rb +30 -0
- data/lib/project_types/rails/commands/serve.rb +47 -0
- data/lib/project_types/rails/commands/tunnel.rb +39 -0
- data/lib/project_types/rails/forms/create.rb +116 -0
- data/lib/project_types/rails/gem.rb +56 -0
- data/lib/project_types/rails/messages/messages.rb +283 -0
- data/lib/project_types/rails/ruby.rb +17 -0
- data/lib/project_types/script/cli.rb +76 -0
- data/lib/project_types/script/commands/create.rb +45 -0
- data/lib/project_types/script/commands/disable.rb +36 -0
- data/lib/project_types/script/commands/enable.rb +46 -0
- data/lib/project_types/script/commands/push.rb +39 -0
- data/lib/project_types/script/config/extension_points.yml +18 -0
- data/lib/project_types/script/errors.rb +16 -0
- data/lib/project_types/script/forms/create.rb +29 -0
- data/lib/project_types/script/forms/enable.rb +24 -0
- data/lib/project_types/script/forms/push.rb +19 -0
- data/lib/project_types/script/forms/script_form.rb +66 -0
- data/lib/project_types/script/graphql/app_script_update_or_create.graphql +27 -0
- data/lib/project_types/script/graphql/script_service_proxy.graphql +8 -0
- data/lib/project_types/script/graphql/shop_script_delete.graphql +14 -0
- data/lib/project_types/script/graphql/shop_script_update_or_create.graphql +28 -0
- data/lib/project_types/script/layers/application/build_script.rb +43 -0
- data/lib/project_types/script/layers/application/create_script.rb +47 -0
- data/lib/project_types/script/layers/application/disable_script.rb +19 -0
- data/lib/project_types/script/layers/application/enable_script.rb +21 -0
- data/lib/project_types/script/layers/application/extension_points.rb +17 -0
- data/lib/project_types/script/layers/application/project_dependencies.rb +34 -0
- data/lib/project_types/script/layers/application/push_script.rb +30 -0
- data/lib/project_types/script/layers/domain/errors.rb +25 -0
- data/lib/project_types/script/layers/domain/extension_point.rb +29 -0
- data/lib/project_types/script/layers/domain/push_package.rb +29 -0
- data/lib/project_types/script/layers/domain/script.rb +18 -0
- data/lib/project_types/script/layers/infrastructure/assemblyscript_dependency_manager.rb +73 -0
- data/lib/project_types/script/layers/infrastructure/assemblyscript_tsconfig.rb +38 -0
- data/lib/project_types/script/layers/infrastructure/assemblyscript_wasm_builder.rb +39 -0
- data/lib/project_types/script/layers/infrastructure/dependency_manager.rb +36 -0
- data/lib/project_types/script/layers/infrastructure/errors.rb +38 -0
- data/lib/project_types/script/layers/infrastructure/extension_point_repository.rb +31 -0
- data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +47 -0
- data/lib/project_types/script/layers/infrastructure/script_builder.rb +34 -0
- data/lib/project_types/script/layers/infrastructure/script_repository.rb +89 -0
- data/lib/project_types/script/layers/infrastructure/script_service.rb +165 -0
- data/lib/project_types/script/layers/infrastructure/test_suite_repository.rb +59 -0
- data/lib/project_types/script/messages/messages.rb +204 -0
- data/lib/project_types/script/script_project.rb +37 -0
- data/lib/project_types/script/templates/ts/as-pect.config.js +21 -0
- data/lib/project_types/script/ui/error_handler.rb +136 -0
- data/lib/project_types/script/ui/strict_spinner.rb +22 -0
- data/lib/rubygems_plugin.rb +18 -0
- data/lib/shopify-cli/admin_api.rb +99 -0
- data/lib/shopify-cli/admin_api/populate_resource_command.rb +165 -0
- data/lib/shopify-cli/admin_api/schema.rb +32 -0
- data/lib/shopify-cli/api.rb +104 -0
- data/lib/shopify-cli/command.rb +67 -0
- data/lib/shopify-cli/commands.rb +28 -0
- data/lib/shopify-cli/commands/connect.rb +108 -0
- data/lib/shopify-cli/commands/create.rb +50 -0
- data/lib/shopify-cli/commands/help.rb +79 -0
- data/lib/shopify-cli/commands/logout.rb +23 -0
- data/lib/shopify-cli/commands/system.rb +135 -0
- data/lib/shopify-cli/commands/version.rb +15 -0
- data/lib/shopify-cli/context.rb +372 -0
- data/lib/shopify-cli/core.rb +9 -0
- data/lib/shopify-cli/core/entry_point.rb +40 -0
- data/lib/shopify-cli/core/executor.rb +21 -0
- data/lib/shopify-cli/core/help_resolver.rb +20 -0
- data/lib/shopify-cli/core/monorail.rb +118 -0
- data/lib/shopify-cli/db.rb +114 -0
- data/lib/shopify-cli/form.rb +40 -0
- data/lib/shopify-cli/git.rb +141 -0
- data/lib/shopify-cli/helpers.rb +5 -0
- data/lib/shopify-cli/helpers/haikunator.rb +92 -0
- data/lib/shopify-cli/heroku.rb +97 -0
- data/lib/shopify-cli/js_deps.rb +110 -0
- data/lib/shopify-cli/js_system.rb +98 -0
- data/lib/shopify-cli/messages/messages.rb +287 -0
- data/lib/shopify-cli/oauth.rb +192 -0
- data/lib/shopify-cli/oauth/servlet.rb +61 -0
- data/lib/shopify-cli/options.rb +40 -0
- data/lib/shopify-cli/packager.rb +116 -0
- data/lib/shopify-cli/partners_api.rb +114 -0
- data/lib/shopify-cli/partners_api/organizations.rb +32 -0
- data/lib/shopify-cli/process_supervision.rb +187 -0
- data/lib/shopify-cli/project.rb +191 -0
- data/lib/shopify-cli/project_type.rb +83 -0
- data/lib/shopify-cli/resources.rb +5 -0
- data/lib/shopify-cli/resources/env_file.rb +96 -0
- data/lib/shopify-cli/sub_command.rb +15 -0
- data/lib/shopify-cli/task.rb +10 -0
- data/lib/shopify-cli/tasks.rb +32 -0
- data/lib/shopify-cli/tasks/create_api_client.rb +29 -0
- data/lib/shopify-cli/tasks/ensure_dev_store.rb +41 -0
- data/lib/shopify-cli/tasks/ensure_env.rb +31 -0
- data/lib/shopify-cli/tasks/ensure_loopback_url.rb +20 -0
- data/lib/shopify-cli/tasks/update_dashboard_urls.rb +44 -0
- data/lib/shopify-cli/tunnel.rb +154 -0
- data/lib/shopify-cli/version.rb +3 -0
- data/lib/shopify_cli.rb +132 -0
- data/shopify-cli.gemspec +40 -0
- data/shopify.fish +12 -0
- data/shopify.sh +11 -0
- data/vendor/deps/cli-kit/REVISION +1 -0
- data/vendor/deps/cli-kit/lib/cli/kit.rb +60 -0
- data/vendor/deps/cli-kit/lib/cli/kit/autocall.rb +21 -0
- data/vendor/deps/cli-kit/lib/cli/kit/base_command.rb +49 -0
- data/vendor/deps/cli-kit/lib/cli/kit/command_registry.rb +94 -0
- data/vendor/deps/cli-kit/lib/cli/kit/config.rb +133 -0
- data/vendor/deps/cli-kit/lib/cli/kit/error_handler.rb +115 -0
- data/vendor/deps/cli-kit/lib/cli/kit/executor.rb +81 -0
- data/vendor/deps/cli-kit/lib/cli/kit/ini.rb +102 -0
- data/vendor/deps/cli-kit/lib/cli/kit/levenshtein.rb +82 -0
- data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +76 -0
- data/vendor/deps/cli-kit/lib/cli/kit/resolver.rb +60 -0
- data/vendor/deps/cli-kit/lib/cli/kit/ruby_backports/enumerable.rb +6 -0
- data/vendor/deps/cli-kit/lib/cli/kit/support.rb +9 -0
- data/vendor/deps/cli-kit/lib/cli/kit/support/test_helper.rb +244 -0
- data/vendor/deps/cli-kit/lib/cli/kit/system.rb +207 -0
- data/vendor/deps/cli-kit/lib/cli/kit/util.rb +189 -0
- data/vendor/deps/cli-kit/lib/cli/kit/version.rb +5 -0
- data/vendor/deps/cli-ui/REVISION +1 -0
- data/vendor/deps/cli-ui/lib/cli/ui.rb +187 -0
- data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +153 -0
- data/vendor/deps/cli-ui/lib/cli/ui/box.rb +15 -0
- data/vendor/deps/cli-ui/lib/cli/ui/color.rb +79 -0
- data/vendor/deps/cli-ui/lib/cli/ui/formatter.rb +179 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +310 -0
- data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +78 -0
- data/vendor/deps/cli-ui/lib/cli/ui/progress.rb +88 -0
- data/vendor/deps/cli-ui/lib/cli/ui/prompt.rb +248 -0
- data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +472 -0
- data/vendor/deps/cli-ui/lib/cli/ui/prompt/options_handler.rb +24 -0
- data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +48 -0
- data/vendor/deps/cli-ui/lib/cli/ui/spinner/async.rb +40 -0
- data/vendor/deps/cli-ui/lib/cli/ui/spinner/spin_group.rb +241 -0
- data/vendor/deps/cli-ui/lib/cli/ui/stdout_router.rb +227 -0
- data/vendor/deps/cli-ui/lib/cli/ui/terminal.rb +36 -0
- data/vendor/deps/cli-ui/lib/cli/ui/truncater.rb +102 -0
- data/vendor/deps/cli-ui/lib/cli/ui/version.rb +5 -0
- data/vendor/deps/smart_properties/REVISION +1 -0
- data/vendor/deps/smart_properties/lib/smart_properties.rb +174 -0
- data/vendor/deps/smart_properties/lib/smart_properties/errors.rb +114 -0
- data/vendor/deps/smart_properties/lib/smart_properties/property.rb +162 -0
- data/vendor/deps/smart_properties/lib/smart_properties/property_collection.rb +83 -0
- data/vendor/deps/smart_properties/lib/smart_properties/validations.rb +8 -0
- data/vendor/deps/smart_properties/lib/smart_properties/validations/ancestor.rb +27 -0
- data/vendor/deps/smart_properties/lib/smart_properties/version.rb +3 -0
- data/vendor/lib/semantic/LICENSE +20 -0
- data/vendor/lib/semantic/semantic.rb +4 -0
- data/vendor/lib/semantic/version.rb +180 -0
- 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 @@
|
|
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
|