fluid_cli 0.1.2
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 +7 -0
- data/README.md +1 -0
- data/dev.yml +5 -0
- data/exe/fluid +24 -0
- data/lib/fluid_cli/api.rb +135 -0
- data/lib/fluid_cli/assets/post_auth_page/index.html.erb +34 -0
- data/lib/fluid_cli/assets/post_auth_page/style.css +58 -0
- data/lib/fluid_cli/command.rb +55 -0
- data/lib/fluid_cli/commands/help.rb +21 -0
- data/lib/fluid_cli/commands/login.rb +30 -0
- data/lib/fluid_cli/commands/logout.rb +38 -0
- data/lib/fluid_cli/commands/switch.rb +23 -0
- data/lib/fluid_cli/commands/theme/common/company_helper.rb +15 -0
- data/lib/fluid_cli/commands/theme/common/root_helper.rb +95 -0
- data/lib/fluid_cli/commands/theme/dev.rb +61 -0
- data/lib/fluid_cli/commands/theme/help.rb +21 -0
- data/lib/fluid_cli/commands/theme/init.rb +46 -0
- data/lib/fluid_cli/commands/theme/pull.rb +68 -0
- data/lib/fluid_cli/commands/theme/push.rb +132 -0
- data/lib/fluid_cli/commands/theme.rb +23 -0
- data/lib/fluid_cli/commands/whoami.rb +23 -0
- data/lib/fluid_cli/commands.rb +19 -0
- data/lib/fluid_cli/company_switcher.rb +69 -0
- data/lib/fluid_cli/context.rb +691 -0
- data/lib/fluid_cli/db.rb +114 -0
- data/lib/fluid_cli/entry_point.rb +10 -0
- data/lib/fluid_cli/environment.rb +32 -0
- data/lib/fluid_cli/file_system_listener.rb +29 -0
- data/lib/fluid_cli/form.rb +42 -0
- data/lib/fluid_cli/git.rb +319 -0
- data/lib/fluid_cli/http_request.rb +54 -0
- data/lib/fluid_cli/identity_auth/servlet.rb +39 -0
- data/lib/fluid_cli/identity_auth.rb +126 -0
- data/lib/fluid_cli/options.rb +38 -0
- data/lib/fluid_cli/theme/dev_server/certificate_manager.rb +79 -0
- data/lib/fluid_cli/theme/dev_server/errors.rb +9 -0
- data/lib/fluid_cli/theme/dev_server/header_hash.rb +98 -0
- data/lib/fluid_cli/theme/dev_server/hooks/file_change_hook.rb +39 -0
- data/lib/fluid_cli/theme/dev_server/hot_reload/resources/hot-reload-no-script.html +27 -0
- data/lib/fluid_cli/theme/dev_server/hot_reload/resources/hot_reload.js +28 -0
- data/lib/fluid_cli/theme/dev_server/hot_reload/resources/sse_client.js +43 -0
- data/lib/fluid_cli/theme/dev_server/hot_reload/resources/theme.js +16 -0
- data/lib/fluid_cli/theme/dev_server/hot_reload/script_injector.rb +54 -0
- data/lib/fluid_cli/theme/dev_server/hot_reload.rb +75 -0
- data/lib/fluid_cli/theme/dev_server/local_assets.rb +92 -0
- data/lib/fluid_cli/theme/dev_server/proxy.rb +235 -0
- data/lib/fluid_cli/theme/dev_server/proxy_param_builder.rb +82 -0
- data/lib/fluid_cli/theme/dev_server/reload_mode.rb +34 -0
- data/lib/fluid_cli/theme/dev_server/sse.rb +75 -0
- data/lib/fluid_cli/theme/dev_server/watcher.rb +57 -0
- data/lib/fluid_cli/theme/dev_server/web_server.rb +140 -0
- data/lib/fluid_cli/theme/dev_server.rb +289 -0
- data/lib/fluid_cli/theme/development_theme.rb +101 -0
- data/lib/fluid_cli/theme/file.rb +105 -0
- data/lib/fluid_cli/theme/forms/select.rb +33 -0
- data/lib/fluid_cli/theme/mime_type.rb +34 -0
- data/lib/fluid_cli/theme/presenters/theme_presenter.rb +49 -0
- data/lib/fluid_cli/theme/presenters/themes_presenter.rb +31 -0
- data/lib/fluid_cli/theme/root.rb +62 -0
- data/lib/fluid_cli/theme/syncer/checksums.rb +66 -0
- data/lib/fluid_cli/theme/syncer/downloader.rb +54 -0
- data/lib/fluid_cli/theme/syncer/error_reporter.rb +45 -0
- data/lib/fluid_cli/theme/syncer/merger.rb +53 -0
- data/lib/fluid_cli/theme/syncer/operation.rb +58 -0
- data/lib/fluid_cli/theme/syncer/standard_reporter.rb +32 -0
- data/lib/fluid_cli/theme/syncer/unsupported_script_warning.rb +90 -0
- data/lib/fluid_cli/theme/syncer/uploader/forms/apply_to_all.rb +41 -0
- data/lib/fluid_cli/theme/syncer/uploader/forms/apply_to_all_form.rb +37 -0
- data/lib/fluid_cli/theme/syncer/uploader/forms/base_strategy_form.rb +64 -0
- data/lib/fluid_cli/theme/syncer/uploader/forms/select_delete_strategy.rb +29 -0
- data/lib/fluid_cli/theme/syncer/uploader/forms/select_update_strategy.rb +30 -0
- data/lib/fluid_cli/theme/syncer/uploader/json_delete_handler.rb +49 -0
- data/lib/fluid_cli/theme/syncer/uploader/json_update_handler.rb +71 -0
- data/lib/fluid_cli/theme/syncer/uploader.rb +105 -0
- data/lib/fluid_cli/theme/syncer.rb +412 -0
- data/lib/fluid_cli/theme/theme.rb +186 -0
- data/lib/fluid_cli/theme/ui/sync_progress_bar.rb +22 -0
- data/lib/fluid_cli/thread_pool/job.rb +35 -0
- data/lib/fluid_cli/thread_pool.rb +49 -0
- data/lib/fluid_cli/version.rb +3 -0
- data/lib/fluid_cli.rb +59 -0
- data/vendor/deps/base64/.document +5 -0
- data/vendor/deps/base64/.gitignore +9 -0
- data/vendor/deps/base64/BSDL +22 -0
- data/vendor/deps/base64/COPYING +56 -0
- data/vendor/deps/base64/Gemfile +9 -0
- data/vendor/deps/base64/LEGAL +60 -0
- data/vendor/deps/base64/README.md +48 -0
- data/vendor/deps/base64/Rakefile +31 -0
- data/vendor/deps/base64/base64.gemspec +28 -0
- data/vendor/deps/base64/bin/console +14 -0
- data/vendor/deps/base64/bin/setup +8 -0
- data/vendor/deps/base64/lib/base64.rb +382 -0
- data/vendor/deps/base64/sig/base64.rbs +358 -0
- data/vendor/deps/base64/test/base64/test_base64.rb +115 -0
- data/vendor/deps/base64/test_sig/test_base64.rb +44 -0
- data/vendor/deps/cli-kit/REVISION +1 -0
- data/vendor/deps/cli-kit/lib/cli/kit/args/definition.rb +286 -0
- data/vendor/deps/cli-kit/lib/cli/kit/args/evaluation.rb +215 -0
- data/vendor/deps/cli-kit/lib/cli/kit/args/parser/node.rb +128 -0
- data/vendor/deps/cli-kit/lib/cli/kit/args/parser.rb +125 -0
- data/vendor/deps/cli-kit/lib/cli/kit/args/tokenizer.rb +130 -0
- data/vendor/deps/cli-kit/lib/cli/kit/args.rb +16 -0
- data/vendor/deps/cli-kit/lib/cli/kit/base_command.rb +30 -0
- data/vendor/deps/cli-kit/lib/cli/kit/command_help.rb +268 -0
- data/vendor/deps/cli-kit/lib/cli/kit/command_registry.rb +150 -0
- data/vendor/deps/cli-kit/lib/cli/kit/config.rb +137 -0
- data/vendor/deps/cli-kit/lib/cli/kit/core_ext.rb +28 -0
- data/vendor/deps/cli-kit/lib/cli/kit/error_handler.rb +166 -0
- data/vendor/deps/cli-kit/lib/cli/kit/executor.rb +92 -0
- data/vendor/deps/cli-kit/lib/cli/kit/ini.rb +91 -0
- data/vendor/deps/cli-kit/lib/cli/kit/levenshtein.rb +92 -0
- data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +94 -0
- data/vendor/deps/cli-kit/lib/cli/kit/opts.rb +248 -0
- data/vendor/deps/cli-kit/lib/cli/kit/parse_args.rb +55 -0
- data/vendor/deps/cli-kit/lib/cli/kit/resolver.rb +66 -0
- data/vendor/deps/cli-kit/lib/cli/kit/support/test_helper.rb +260 -0
- data/vendor/deps/cli-kit/lib/cli/kit/support.rb +11 -0
- data/vendor/deps/cli-kit/lib/cli/kit/system.rb +290 -0
- data/vendor/deps/cli-kit/lib/cli/kit/util.rb +118 -0
- data/vendor/deps/cli-kit/lib/cli/kit/version.rb +7 -0
- data/vendor/deps/cli-kit/lib/cli/kit.rb +139 -0
- data/vendor/deps/cli-ui/REVISION +1 -0
- data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +218 -0
- data/vendor/deps/cli-ui/lib/cli/ui/color.rb +101 -0
- data/vendor/deps/cli-ui/lib/cli/ui/formatter.rb +219 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_stack.rb +67 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style/box.rb +179 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style/bracket.rb +152 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style.rb +127 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +286 -0
- data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +92 -0
- data/vendor/deps/cli-ui/lib/cli/ui/os.rb +63 -0
- data/vendor/deps/cli-ui/lib/cli/ui/printer.rb +64 -0
- data/vendor/deps/cli-ui/lib/cli/ui/progress.rb +132 -0
- data/vendor/deps/cli-ui/lib/cli/ui/progress_reporter.rb +209 -0
- data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +583 -0
- data/vendor/deps/cli-ui/lib/cli/ui/prompt/options_handler.rb +36 -0
- data/vendor/deps/cli-ui/lib/cli/ui/prompt.rb +381 -0
- data/vendor/deps/cli-ui/lib/cli/ui/spinner/async.rb +48 -0
- data/vendor/deps/cli-ui/lib/cli/ui/spinner/spin_group.rb +602 -0
- data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +79 -0
- data/vendor/deps/cli-ui/lib/cli/ui/stdout_router.rb +399 -0
- data/vendor/deps/cli-ui/lib/cli/ui/table.rb +83 -0
- data/vendor/deps/cli-ui/lib/cli/ui/terminal.rb +55 -0
- data/vendor/deps/cli-ui/lib/cli/ui/truncater.rb +106 -0
- data/vendor/deps/cli-ui/lib/cli/ui/version.rb +8 -0
- data/vendor/deps/cli-ui/lib/cli/ui/widgets/base.rb +46 -0
- data/vendor/deps/cli-ui/lib/cli/ui/widgets/status.rb +79 -0
- data/vendor/deps/cli-ui/lib/cli/ui/widgets.rb +89 -0
- data/vendor/deps/cli-ui/lib/cli/ui/work_queue.rb +142 -0
- data/vendor/deps/cli-ui/lib/cli/ui/wrap.rb +61 -0
- data/vendor/deps/cli-ui/lib/cli/ui.rb +359 -0
- data/vendor/deps/cli-ui/vendor/reentrant_mutex.rb +78 -0
- data/vendor/deps/debug/CONTRIBUTING.md +573 -0
- data/vendor/deps/debug/Gemfile +10 -0
- data/vendor/deps/debug/LICENSE.txt +22 -0
- data/vendor/deps/debug/README.md +996 -0
- data/vendor/deps/debug/Rakefile +57 -0
- data/vendor/deps/debug/TODO.md +23 -0
- data/vendor/deps/debug/debug.gemspec +33 -0
- data/vendor/deps/debug/exe/rdbg +53 -0
- data/vendor/deps/debug/ext/debug/Makefile +273 -0
- data/vendor/deps/debug/ext/debug/debug.c +228 -0
- data/vendor/deps/debug/ext/debug/debug_version.h +1 -0
- data/vendor/deps/debug/ext/debug/extconf.rb +27 -0
- data/vendor/deps/debug/ext/debug/iseq_collector.c +93 -0
- data/vendor/deps/debug/lib/debug/abbrev_command.rb +77 -0
- data/vendor/deps/debug/lib/debug/breakpoint.rb +556 -0
- data/vendor/deps/debug/lib/debug/client.rb +263 -0
- data/vendor/deps/debug/lib/debug/color.rb +123 -0
- data/vendor/deps/debug/lib/debug/config.rb +592 -0
- data/vendor/deps/debug/lib/debug/console.rb +224 -0
- data/vendor/deps/debug/lib/debug/dap_custom/traceInspector.rb +336 -0
- data/vendor/deps/debug/lib/debug/debug.bundle +0 -0
- data/vendor/deps/debug/lib/debug/frame_info.rb +190 -0
- data/vendor/deps/debug/lib/debug/irb_integration.rb +37 -0
- data/vendor/deps/debug/lib/debug/local.rb +115 -0
- data/vendor/deps/debug/lib/debug/open.rb +13 -0
- data/vendor/deps/debug/lib/debug/open_nonstop.rb +15 -0
- data/vendor/deps/debug/lib/debug/prelude.rb +50 -0
- data/vendor/deps/debug/lib/debug/server.rb +534 -0
- data/vendor/deps/debug/lib/debug/server_cdp.rb +1348 -0
- data/vendor/deps/debug/lib/debug/server_dap.rb +1108 -0
- data/vendor/deps/debug/lib/debug/session.rb +2667 -0
- data/vendor/deps/debug/lib/debug/source_repository.rb +150 -0
- data/vendor/deps/debug/lib/debug/start.rb +5 -0
- data/vendor/deps/debug/lib/debug/thread_client.rb +1457 -0
- data/vendor/deps/debug/lib/debug/tracer.rb +241 -0
- data/vendor/deps/debug/lib/debug/version.rb +5 -0
- data/vendor/deps/debug/lib/debug.rb +9 -0
- data/vendor/deps/debug/misc/README.md.erb +660 -0
- data/vendor/deps/listen/.github/release-drafter.yml +17 -0
- data/vendor/deps/listen/.github/workflows/development.yml +67 -0
- data/vendor/deps/listen/.github/workflows/push.yml +12 -0
- data/vendor/deps/listen/.gitignore +28 -0
- data/vendor/deps/listen/.rspec +3 -0
- data/vendor/deps/listen/.rubocop.yml +283 -0
- data/vendor/deps/listen/.yardopts +11 -0
- data/vendor/deps/listen/CHANGELOG.md +1 -0
- data/vendor/deps/listen/CONTRIBUTING.md +45 -0
- data/vendor/deps/listen/Gemfile +33 -0
- data/vendor/deps/listen/Guardfile +26 -0
- data/vendor/deps/listen/LICENSE.txt +22 -0
- data/vendor/deps/listen/README.md +490 -0
- data/vendor/deps/listen/Rakefile +154 -0
- data/vendor/deps/listen/bin/listen +11 -0
- data/vendor/deps/listen/lib/listen/adapter/base.rb +129 -0
- data/vendor/deps/listen/lib/listen/adapter/bsd.rb +104 -0
- data/vendor/deps/listen/lib/listen/adapter/config.rb +31 -0
- data/vendor/deps/listen/lib/listen/adapter/darwin.rb +77 -0
- data/vendor/deps/listen/lib/listen/adapter/linux.rb +108 -0
- data/vendor/deps/listen/lib/listen/adapter/polling.rb +40 -0
- data/vendor/deps/listen/lib/listen/adapter/windows.rb +96 -0
- data/vendor/deps/listen/lib/listen/adapter.rb +43 -0
- data/vendor/deps/listen/lib/listen/backend.rb +40 -0
- data/vendor/deps/listen/lib/listen/change.rb +69 -0
- data/vendor/deps/listen/lib/listen/cli.rb +65 -0
- data/vendor/deps/listen/lib/listen/directory.rb +93 -0
- data/vendor/deps/listen/lib/listen/error.rb +11 -0
- data/vendor/deps/listen/lib/listen/event/config.rb +39 -0
- data/vendor/deps/listen/lib/listen/event/loop.rb +92 -0
- data/vendor/deps/listen/lib/listen/event/processor.rb +128 -0
- data/vendor/deps/listen/lib/listen/event/queue.rb +52 -0
- data/vendor/deps/listen/lib/listen/file.rb +95 -0
- data/vendor/deps/listen/lib/listen/fsm.rb +131 -0
- data/vendor/deps/listen/lib/listen/listener/config.rb +41 -0
- data/vendor/deps/listen/lib/listen/listener.rb +136 -0
- data/vendor/deps/listen/lib/listen/logger.rb +65 -0
- data/vendor/deps/listen/lib/listen/monotonic_time.rb +27 -0
- data/vendor/deps/listen/lib/listen/options.rb +24 -0
- data/vendor/deps/listen/lib/listen/queue_optimizer.rb +129 -0
- data/vendor/deps/listen/lib/listen/record/entry.rb +66 -0
- data/vendor/deps/listen/lib/listen/record/symlink_detector.rb +47 -0
- data/vendor/deps/listen/lib/listen/record.rb +122 -0
- data/vendor/deps/listen/lib/listen/silencer/controller.rb +50 -0
- data/vendor/deps/listen/lib/listen/silencer.rb +106 -0
- data/vendor/deps/listen/lib/listen/thread.rb +54 -0
- data/vendor/deps/listen/lib/listen/version.rb +5 -0
- data/vendor/deps/listen/lib/listen.rb +47 -0
- data/vendor/deps/listen/listen.gemspec +40 -0
- data/vendor/deps/listen/spec/acceptance/listen_spec.rb +320 -0
- data/vendor/deps/listen/spec/lib/listen/adapter/base_spec.rb +101 -0
- data/vendor/deps/listen/spec/lib/listen/adapter/bsd_spec.rb +13 -0
- data/vendor/deps/listen/spec/lib/listen/adapter/config_spec.rb +122 -0
- data/vendor/deps/listen/spec/lib/listen/adapter/darwin_spec.rb +82 -0
- data/vendor/deps/listen/spec/lib/listen/adapter/linux_spec.rb +199 -0
- data/vendor/deps/listen/spec/lib/listen/adapter/polling_spec.rb +83 -0
- data/vendor/deps/listen/spec/lib/listen/adapter/windows_spec.rb +13 -0
- data/vendor/deps/listen/spec/lib/listen/adapter_spec.rb +69 -0
- data/vendor/deps/listen/spec/lib/listen/backend_spec.rb +82 -0
- data/vendor/deps/listen/spec/lib/listen/change_spec.rb +102 -0
- data/vendor/deps/listen/spec/lib/listen/cli_spec.rb +116 -0
- data/vendor/deps/listen/spec/lib/listen/directory_spec.rb +284 -0
- data/vendor/deps/listen/spec/lib/listen/event/config_spec.rb +33 -0
- data/vendor/deps/listen/spec/lib/listen/event/loop_spec.rb +118 -0
- data/vendor/deps/listen/spec/lib/listen/event/processor_spec.rb +250 -0
- data/vendor/deps/listen/spec/lib/listen/event/queue_spec.rb +118 -0
- data/vendor/deps/listen/spec/lib/listen/file_spec.rb +254 -0
- data/vendor/deps/listen/spec/lib/listen/fsm_spec.rb +147 -0
- data/vendor/deps/listen/spec/lib/listen/listener/config_spec.rb +29 -0
- data/vendor/deps/listen/spec/lib/listen/listener_spec.rb +321 -0
- data/vendor/deps/listen/spec/lib/listen/logger_spec.rb +212 -0
- data/vendor/deps/listen/spec/lib/listen/monotonic_time_spec.rb +58 -0
- data/vendor/deps/listen/spec/lib/listen/queue_optimizer_spec.rb +111 -0
- data/vendor/deps/listen/spec/lib/listen/record_spec.rb +424 -0
- data/vendor/deps/listen/spec/lib/listen/silencer/controller_spec.rb +97 -0
- data/vendor/deps/listen/spec/lib/listen/silencer_spec.rb +109 -0
- data/vendor/deps/listen/spec/lib/listen/thread_spec.rb +133 -0
- data/vendor/deps/listen/spec/lib/listen_spec.rb +25 -0
- data/vendor/deps/listen/spec/spec_helper.rb +49 -0
- data/vendor/deps/listen/spec/support/acceptance_helper.rb +260 -0
- data/vendor/deps/listen/spec/support/fixtures_helper.rb +32 -0
- data/vendor/deps/listen/spec/support/platform_helper.rb +17 -0
- data/vendor/deps/observer/.github/dependabot.yml +6 -0
- data/vendor/deps/observer/.github/workflows/test.yml +33 -0
- data/vendor/deps/observer/.gitignore +8 -0
- data/vendor/deps/observer/BSDL +22 -0
- data/vendor/deps/observer/COPYING +56 -0
- data/vendor/deps/observer/Gemfile +9 -0
- data/vendor/deps/observer/README.md +139 -0
- data/vendor/deps/observer/Rakefile +10 -0
- data/vendor/deps/observer/bin/console +14 -0
- data/vendor/deps/observer/bin/setup +8 -0
- data/vendor/deps/observer/lib/observer.rb +229 -0
- data/vendor/deps/observer/observer.gemspec +32 -0
- data/vendor/deps/observer/test/test_observer.rb +66 -0
- data/vendor/deps/webrick/.gitignore +9 -0
- data/vendor/deps/webrick/Gemfile +3 -0
- data/vendor/deps/webrick/LICENSE.txt +22 -0
- data/vendor/deps/webrick/README.md +61 -0
- data/vendor/deps/webrick/Rakefile +10 -0
- data/vendor/deps/webrick/lib/webrick/accesslog.rb +157 -0
- data/vendor/deps/webrick/lib/webrick/cgi.rb +313 -0
- data/vendor/deps/webrick/lib/webrick/compat.rb +36 -0
- data/vendor/deps/webrick/lib/webrick/config.rb +158 -0
- data/vendor/deps/webrick/lib/webrick/cookie.rb +172 -0
- data/vendor/deps/webrick/lib/webrick/htmlutils.rb +30 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/authenticator.rb +117 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/basicauth.rb +116 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/digestauth.rb +395 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/htdigest.rb +132 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/htgroup.rb +97 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/htpasswd.rb +158 -0
- data/vendor/deps/webrick/lib/webrick/httpauth/userdb.rb +53 -0
- data/vendor/deps/webrick/lib/webrick/httpauth.rb +96 -0
- data/vendor/deps/webrick/lib/webrick/httpproxy.rb +354 -0
- data/vendor/deps/webrick/lib/webrick/httprequest.rb +636 -0
- data/vendor/deps/webrick/lib/webrick/httpresponse.rb +564 -0
- data/vendor/deps/webrick/lib/webrick/https.rb +152 -0
- data/vendor/deps/webrick/lib/webrick/httpserver.rb +294 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet/abstract.rb +152 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet/cgi_runner.rb +47 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet/cgihandler.rb +126 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet/erbhandler.rb +88 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet/filehandler.rb +552 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet/prochandler.rb +47 -0
- data/vendor/deps/webrick/lib/webrick/httpservlet.rb +23 -0
- data/vendor/deps/webrick/lib/webrick/httpstatus.rb +194 -0
- data/vendor/deps/webrick/lib/webrick/httputils.rb +512 -0
- data/vendor/deps/webrick/lib/webrick/httpversion.rb +76 -0
- data/vendor/deps/webrick/lib/webrick/log.rb +156 -0
- data/vendor/deps/webrick/lib/webrick/server.rb +381 -0
- data/vendor/deps/webrick/lib/webrick/ssl.rb +215 -0
- data/vendor/deps/webrick/lib/webrick/utils.rb +265 -0
- data/vendor/deps/webrick/lib/webrick/version.rb +18 -0
- data/vendor/deps/webrick/lib/webrick.rb +232 -0
- data/vendor/deps/webrick/webrick.gemspec +74 -0
- metadata +412 -0
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative '../work_queue'
|
|
5
|
+
|
|
6
|
+
module CLI
|
|
7
|
+
module UI
|
|
8
|
+
module Spinner
|
|
9
|
+
class SpinGroup
|
|
10
|
+
DEFAULT_FINAL_GLYPH = ->(success) { success ? CLI::UI::Glyph::CHECK : CLI::UI::Glyph::X }
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
#: Mutex
|
|
14
|
+
attr_reader :pause_mutex
|
|
15
|
+
|
|
16
|
+
#: -> bool
|
|
17
|
+
def paused?
|
|
18
|
+
@paused
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
#: [T] { -> T } -> T
|
|
22
|
+
def pause_spinners(&block)
|
|
23
|
+
previous_paused = nil #: bool?
|
|
24
|
+
@pause_mutex.synchronize do
|
|
25
|
+
previous_paused = @paused
|
|
26
|
+
@paused = true
|
|
27
|
+
end
|
|
28
|
+
block.call
|
|
29
|
+
ensure
|
|
30
|
+
@pause_mutex.synchronize do
|
|
31
|
+
@paused = previous_paused
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
@pause_mutex = Mutex.new
|
|
37
|
+
@paused = false
|
|
38
|
+
|
|
39
|
+
# Initializes a new spin group
|
|
40
|
+
# This lets you add +Task+ objects to the group to multi-thread work
|
|
41
|
+
#
|
|
42
|
+
# ==== Options
|
|
43
|
+
#
|
|
44
|
+
# * +:auto_debrief+ - Automatically debrief exceptions or through success_debrief? Default to true
|
|
45
|
+
# * +:interrupt_debrief+ - Automatically debrief on interrupt. Default to false
|
|
46
|
+
# * +:max_concurrent+ - Maximum number of concurrent tasks. Default is 0 (effectively unlimited)
|
|
47
|
+
# * +:work_queue+ - Custom WorkQueue instance. If not provided, a new one will be created
|
|
48
|
+
# * +:to+ - Target stream, like $stdout or $stderr. Can be anything with print and puts methods,
|
|
49
|
+
# or under Sorbet, IO or StringIO. Defaults to $stdout
|
|
50
|
+
#
|
|
51
|
+
# ==== Example Usage
|
|
52
|
+
#
|
|
53
|
+
# CLI::UI::SpinGroup.new do |spin_group|
|
|
54
|
+
# spin_group.add('Title') { |spinner| sleep 3.0 }
|
|
55
|
+
# spin_group.add('Title 2') { |spinner| sleep 3.0; spinner.update_title('New Title'); sleep 3.0 }
|
|
56
|
+
# end
|
|
57
|
+
#
|
|
58
|
+
# Output:
|
|
59
|
+
#
|
|
60
|
+
# https://user-images.githubusercontent.com/3074765/33798558-c452fa26-dce8-11e7-9e90-b4b34df21a46.gif
|
|
61
|
+
#
|
|
62
|
+
#: (?auto_debrief: bool, ?interrupt_debrief: bool, ?max_concurrent: Integer, ?work_queue: WorkQueue?, ?to: io_like) -> void
|
|
63
|
+
def initialize(auto_debrief: true, interrupt_debrief: false, max_concurrent: 0, work_queue: nil, to: $stdout)
|
|
64
|
+
@m = Mutex.new
|
|
65
|
+
@tasks = []
|
|
66
|
+
@puts_above = []
|
|
67
|
+
@auto_debrief = auto_debrief
|
|
68
|
+
@interrupt_debrief = interrupt_debrief
|
|
69
|
+
@start = Time.new
|
|
70
|
+
@stopped = false
|
|
71
|
+
@internal_work_queue = work_queue.nil?
|
|
72
|
+
@work_queue = work_queue || WorkQueue.new(max_concurrent.zero? ? 1024 : max_concurrent) #: WorkQueue
|
|
73
|
+
if block_given?
|
|
74
|
+
yield self
|
|
75
|
+
wait(to: to)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
class Task
|
|
80
|
+
#: String
|
|
81
|
+
attr_reader :title, :stdout, :stderr
|
|
82
|
+
|
|
83
|
+
#: bool
|
|
84
|
+
attr_reader :success
|
|
85
|
+
|
|
86
|
+
#: bool
|
|
87
|
+
attr_reader :done
|
|
88
|
+
|
|
89
|
+
#: Exception?
|
|
90
|
+
attr_reader :exception
|
|
91
|
+
|
|
92
|
+
#: Integer?
|
|
93
|
+
attr_reader :progress_percentage
|
|
94
|
+
|
|
95
|
+
# Initializes a new Task
|
|
96
|
+
# This is managed entirely internally by +SpinGroup+
|
|
97
|
+
#
|
|
98
|
+
# ==== Attributes
|
|
99
|
+
#
|
|
100
|
+
# * +title+ - Title of the task
|
|
101
|
+
# * +block+ - Block for the task, will be provided with an instance of the spinner
|
|
102
|
+
#
|
|
103
|
+
#: (String title, final_glyph: ^(bool success) -> (Glyph | String), merged_output: bool, duplicate_output_to: IO, work_queue: WorkQueue) { (Task task) -> untyped } -> void
|
|
104
|
+
def initialize(title, final_glyph:, merged_output:, duplicate_output_to:, work_queue:, &block)
|
|
105
|
+
@title = title
|
|
106
|
+
@final_glyph = final_glyph
|
|
107
|
+
@always_full_render = title =~ Formatter::SCAN_WIDGET
|
|
108
|
+
@future = work_queue.enqueue do
|
|
109
|
+
cap = CLI::UI::StdoutRouter::Capture.new(
|
|
110
|
+
merged_output: merged_output, duplicate_output_to: duplicate_output_to,
|
|
111
|
+
) { block.call(self) }
|
|
112
|
+
begin
|
|
113
|
+
cap.run
|
|
114
|
+
ensure
|
|
115
|
+
@stdout = cap.stdout
|
|
116
|
+
@stderr = cap.stderr
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
@m = Mutex.new
|
|
121
|
+
@force_full_render = false
|
|
122
|
+
@done = false
|
|
123
|
+
@exception = nil
|
|
124
|
+
@success = false
|
|
125
|
+
@progress_percentage = nil
|
|
126
|
+
@wants_progress_mode = false
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
#: { (Task task) -> void } -> void
|
|
130
|
+
def on_done(&block)
|
|
131
|
+
@on_done = block
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Checks if a task is finished
|
|
135
|
+
#
|
|
136
|
+
#: -> bool
|
|
137
|
+
def check
|
|
138
|
+
return true if @done
|
|
139
|
+
return false unless @future.completed?
|
|
140
|
+
|
|
141
|
+
@done = true
|
|
142
|
+
begin
|
|
143
|
+
result = @future.value
|
|
144
|
+
@success = true
|
|
145
|
+
@success = false if result == TASK_FAILED
|
|
146
|
+
rescue => exc
|
|
147
|
+
@exception = exc
|
|
148
|
+
@success = false
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
@on_done&.call(self)
|
|
152
|
+
|
|
153
|
+
@done
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Re-renders the task if required:
|
|
157
|
+
#
|
|
158
|
+
# We try to be as lazy as possible in re-rendering the full line. The
|
|
159
|
+
# spinner rune will change on each render for the most part, but the
|
|
160
|
+
# body text will rarely have changed. If the body text *has* changed,
|
|
161
|
+
# we set @force_full_render.
|
|
162
|
+
#
|
|
163
|
+
# Further, if the title string includes any CLI::UI::Widgets, we
|
|
164
|
+
# assume that it may change from render to render, since those
|
|
165
|
+
# evaluate more dynamically than the rest of our format codes, which
|
|
166
|
+
# are just text formatters. This is controlled by @always_full_render.
|
|
167
|
+
#
|
|
168
|
+
# ==== Attributes
|
|
169
|
+
#
|
|
170
|
+
# * +index+ - index of the task
|
|
171
|
+
# * +force+ - force rerender of the task
|
|
172
|
+
# * +width+ - current terminal width to format for
|
|
173
|
+
#
|
|
174
|
+
#: (Integer index, ?bool force, ?width: Integer) -> String
|
|
175
|
+
def render(index, force = true, width: CLI::UI::Terminal.width)
|
|
176
|
+
@m.synchronize do
|
|
177
|
+
if !CLI::UI.enable_cursor? || force || @always_full_render || @force_full_render
|
|
178
|
+
full_render(index, width)
|
|
179
|
+
else
|
|
180
|
+
partial_render(index)
|
|
181
|
+
end
|
|
182
|
+
ensure
|
|
183
|
+
@force_full_render = false
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Update the spinner title
|
|
188
|
+
#
|
|
189
|
+
# ==== Attributes
|
|
190
|
+
#
|
|
191
|
+
# * +title+ - title to change the spinner to
|
|
192
|
+
#
|
|
193
|
+
#: (String new_title) -> void
|
|
194
|
+
def update_title(new_title)
|
|
195
|
+
@m.synchronize do
|
|
196
|
+
@always_full_render = new_title =~ Formatter::SCAN_WIDGET
|
|
197
|
+
@title = new_title
|
|
198
|
+
@force_full_render = true
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# Set progress percentage (0-100) and switch to progress mode
|
|
203
|
+
#: (Integer percentage) -> void
|
|
204
|
+
def set_progress(percentage) # rubocop:disable Naming/AccessorMethodName
|
|
205
|
+
@m.synchronize do
|
|
206
|
+
@progress_percentage = percentage.clamp(0, 100)
|
|
207
|
+
@wants_progress_mode = true
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# Switch back to indeterminate mode
|
|
212
|
+
#: -> void
|
|
213
|
+
def clear_progress
|
|
214
|
+
@m.synchronize do
|
|
215
|
+
@progress_percentage = nil
|
|
216
|
+
@wants_progress_mode = false
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# Check if this task wants progress mode
|
|
221
|
+
#: -> bool
|
|
222
|
+
def wants_progress_mode?
|
|
223
|
+
@m.synchronize { @wants_progress_mode }
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# Get current progress percentage
|
|
227
|
+
#: -> Integer?
|
|
228
|
+
def current_progress
|
|
229
|
+
@m.synchronize { @progress_percentage }
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
private
|
|
233
|
+
|
|
234
|
+
#: (Integer index, Integer terminal_width) -> String
|
|
235
|
+
def full_render(index, terminal_width)
|
|
236
|
+
o = +''
|
|
237
|
+
|
|
238
|
+
o << inset
|
|
239
|
+
o << glyph(index)
|
|
240
|
+
o << ' '
|
|
241
|
+
|
|
242
|
+
truncation_width = terminal_width - CLI::UI::ANSI.printing_width(o)
|
|
243
|
+
|
|
244
|
+
o << CLI::UI.resolve_text(title, truncate_to: truncation_width)
|
|
245
|
+
o << ANSI.clear_to_end_of_line if CLI::UI.enable_cursor?
|
|
246
|
+
|
|
247
|
+
o
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
#: (Integer index) -> String
|
|
251
|
+
def partial_render(index)
|
|
252
|
+
o = +''
|
|
253
|
+
|
|
254
|
+
o << CLI::UI::ANSI.cursor_forward(inset_width)
|
|
255
|
+
o << glyph(index)
|
|
256
|
+
|
|
257
|
+
o
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
#: (Integer index) -> String
|
|
261
|
+
def glyph(index)
|
|
262
|
+
if @done
|
|
263
|
+
final_glyph = @final_glyph.call(@success)
|
|
264
|
+
if final_glyph.is_a?(Glyph)
|
|
265
|
+
CLI::UI.enable_color? ? final_glyph.to_s : final_glyph.char
|
|
266
|
+
else
|
|
267
|
+
final_glyph
|
|
268
|
+
end
|
|
269
|
+
elsif CLI::UI.enable_cursor?
|
|
270
|
+
if !@future.started?
|
|
271
|
+
CLI::UI.enable_color? ? Glyph::HOURGLASS.to_s : Glyph::HOURGLASS.char
|
|
272
|
+
else
|
|
273
|
+
CLI::UI.enable_color? ? GLYPHS[index] : RUNES[index]
|
|
274
|
+
end
|
|
275
|
+
else
|
|
276
|
+
Glyph::HOURGLASS.char
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
#: -> String
|
|
281
|
+
def inset
|
|
282
|
+
@inset ||= CLI::UI::Frame.prefix
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
#: -> Integer
|
|
286
|
+
def inset_width
|
|
287
|
+
@inset_width ||= CLI::UI::ANSI.printing_width(inset)
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
# Add a new task
|
|
292
|
+
#
|
|
293
|
+
# ==== Attributes
|
|
294
|
+
#
|
|
295
|
+
# * +title+ - Title of the task
|
|
296
|
+
# * +block+ - Block for the task, will be provided with an instance of the spinner
|
|
297
|
+
#
|
|
298
|
+
# ==== Example Usage:
|
|
299
|
+
# spin_group = CLI::UI::SpinGroup.new
|
|
300
|
+
# spin_group.add('Title') { |spinner| sleep 1.0 }
|
|
301
|
+
# spin_group.wait
|
|
302
|
+
#
|
|
303
|
+
#: (String title, ?final_glyph: ^(bool success) -> (Glyph | String), ?merged_output: bool, ?duplicate_output_to: IO) { (Task task) -> void } -> void
|
|
304
|
+
def add(
|
|
305
|
+
title,
|
|
306
|
+
final_glyph: DEFAULT_FINAL_GLYPH,
|
|
307
|
+
merged_output: false,
|
|
308
|
+
duplicate_output_to: File.new(File::NULL, 'w'),
|
|
309
|
+
&block
|
|
310
|
+
)
|
|
311
|
+
@m.synchronize do
|
|
312
|
+
@tasks << Task.new(
|
|
313
|
+
title,
|
|
314
|
+
final_glyph: final_glyph,
|
|
315
|
+
merged_output: merged_output,
|
|
316
|
+
duplicate_output_to: duplicate_output_to,
|
|
317
|
+
work_queue: @work_queue,
|
|
318
|
+
&block
|
|
319
|
+
)
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
#: -> void
|
|
324
|
+
def stop
|
|
325
|
+
# If we already own the mutex (called from within another synchronized block),
|
|
326
|
+
# set stopped directly to avoid deadlock
|
|
327
|
+
if @m.owned?
|
|
328
|
+
return if @stopped
|
|
329
|
+
|
|
330
|
+
@stopped = true
|
|
331
|
+
else
|
|
332
|
+
@m.synchronize do
|
|
333
|
+
return if @stopped
|
|
334
|
+
|
|
335
|
+
@stopped = true
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
# Interrupt is thread-safe on its own, so we can call it outside the mutex
|
|
339
|
+
@work_queue.interrupt
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
#: -> bool
|
|
343
|
+
def stopped?
|
|
344
|
+
if @m.owned?
|
|
345
|
+
@stopped
|
|
346
|
+
else
|
|
347
|
+
@m.synchronize { @stopped }
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
# Tells the group you're done adding tasks and to wait for all of them to finish
|
|
352
|
+
#
|
|
353
|
+
# ==== Options
|
|
354
|
+
#
|
|
355
|
+
# * +:to+ - Target stream, like $stdout or $stderr. Can be anything with print and puts methods,
|
|
356
|
+
# or under Sorbet, IO or StringIO. Defaults to $stdout
|
|
357
|
+
#
|
|
358
|
+
# ==== Example Usage:
|
|
359
|
+
# spin_group = CLI::UI::SpinGroup.new
|
|
360
|
+
# spin_group.add('Title') { |spinner| sleep 1.0 }
|
|
361
|
+
# spin_group.wait
|
|
362
|
+
#
|
|
363
|
+
#: (?to: io_like) -> bool
|
|
364
|
+
def wait(to: $stdout)
|
|
365
|
+
result = false #: bool
|
|
366
|
+
|
|
367
|
+
CLI::UI::ProgressReporter.with_progress(mode: :indeterminate, to: to, delay_start: true) do |reporter|
|
|
368
|
+
idx = 0
|
|
369
|
+
consumed_lines = 0
|
|
370
|
+
|
|
371
|
+
@work_queue.close if @internal_work_queue
|
|
372
|
+
|
|
373
|
+
tasks_seen = @tasks.map { false }
|
|
374
|
+
tasks_seen_done = @tasks.map { false }
|
|
375
|
+
|
|
376
|
+
current_mode = :indeterminate #: Symbol
|
|
377
|
+
first_render = true #: bool
|
|
378
|
+
|
|
379
|
+
loop do
|
|
380
|
+
break if stopped?
|
|
381
|
+
|
|
382
|
+
done_count = 0
|
|
383
|
+
width = CLI::UI::Terminal.width
|
|
384
|
+
|
|
385
|
+
# Update progress mode based on task states
|
|
386
|
+
current_mode = update_progress_mode(reporter, current_mode, first_render)
|
|
387
|
+
|
|
388
|
+
self.class.pause_mutex.synchronize do
|
|
389
|
+
next if self.class.paused?
|
|
390
|
+
|
|
391
|
+
@m.synchronize do
|
|
392
|
+
CLI::UI.raw do
|
|
393
|
+
# Render any messages above the spinner
|
|
394
|
+
force_full_render = render_puts_above(to, consumed_lines)
|
|
395
|
+
|
|
396
|
+
# Render all tasks
|
|
397
|
+
done_count, consumed_lines = render_tasks(
|
|
398
|
+
to: to,
|
|
399
|
+
tasks_seen: tasks_seen,
|
|
400
|
+
tasks_seen_done: tasks_seen_done,
|
|
401
|
+
consumed_lines: consumed_lines,
|
|
402
|
+
idx: idx,
|
|
403
|
+
force_full_render: force_full_render,
|
|
404
|
+
width: width,
|
|
405
|
+
)
|
|
406
|
+
end
|
|
407
|
+
end
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
break if done_count == @tasks.size
|
|
411
|
+
|
|
412
|
+
# After first render, start the progress reporter in indeterminate mode
|
|
413
|
+
if first_render
|
|
414
|
+
reporter.force_set_indeterminate
|
|
415
|
+
first_render = false
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
idx = (idx + 1) % GLYPHS.size
|
|
419
|
+
Spinner.index = idx
|
|
420
|
+
sleep(PERIOD)
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
# Show error state briefly if tasks failed
|
|
424
|
+
success = all_succeeded?
|
|
425
|
+
unless success
|
|
426
|
+
reporter.set_error
|
|
427
|
+
sleep(0.5)
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
result = if @auto_debrief
|
|
431
|
+
debrief(to: to)
|
|
432
|
+
else
|
|
433
|
+
all_succeeded?
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
result
|
|
438
|
+
rescue Interrupt
|
|
439
|
+
@work_queue.interrupt
|
|
440
|
+
debrief(to: to) if @interrupt_debrief
|
|
441
|
+
stopped? ? false : raise
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
#: (String message) -> void
|
|
445
|
+
def puts_above(message)
|
|
446
|
+
@m.synchronize do
|
|
447
|
+
@puts_above << message
|
|
448
|
+
end
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
# Provide an alternative debriefing for failed tasks
|
|
452
|
+
#: { (String title, Exception? exception, String out, String err) -> void } -> void
|
|
453
|
+
def failure_debrief(&block)
|
|
454
|
+
@failure_debrief = block
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
# Provide a debriefing for successful tasks
|
|
458
|
+
#: { (String title, String out, String err) -> void } -> void
|
|
459
|
+
def success_debrief(&block)
|
|
460
|
+
@success_debrief = block
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
#: -> bool
|
|
464
|
+
def all_succeeded?
|
|
465
|
+
@m.synchronize do
|
|
466
|
+
@tasks.all?(&:success)
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
private
|
|
471
|
+
|
|
472
|
+
# Update progress reporter mode based on task progress states
|
|
473
|
+
#: (CLI::UI::ProgressReporter::Reporter reporter, Symbol current_mode, bool first_render) -> Symbol
|
|
474
|
+
def update_progress_mode(reporter, current_mode, first_render)
|
|
475
|
+
# Don't emit OSC on first iteration
|
|
476
|
+
return current_mode if first_render
|
|
477
|
+
|
|
478
|
+
# Check if any task wants progress mode
|
|
479
|
+
task_with_progress = @tasks.find(&:wants_progress_mode?)
|
|
480
|
+
|
|
481
|
+
if task_with_progress
|
|
482
|
+
progress = task_with_progress.current_progress
|
|
483
|
+
if progress
|
|
484
|
+
reporter.force_set_progress(progress)
|
|
485
|
+
if current_mode != :progress
|
|
486
|
+
# Switch to progress mode
|
|
487
|
+
:progress
|
|
488
|
+
else
|
|
489
|
+
# Update progress
|
|
490
|
+
current_mode
|
|
491
|
+
end
|
|
492
|
+
else
|
|
493
|
+
current_mode
|
|
494
|
+
end
|
|
495
|
+
elsif current_mode != :indeterminate
|
|
496
|
+
# No task wants progress, switch back to indeterminate
|
|
497
|
+
reporter.force_set_indeterminate
|
|
498
|
+
:indeterminate
|
|
499
|
+
else
|
|
500
|
+
current_mode
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
# Render messages that should appear above the spinner
|
|
505
|
+
#: (io_like to, Integer consumed_lines) -> bool
|
|
506
|
+
def render_puts_above(to, consumed_lines)
|
|
507
|
+
return false if @puts_above.empty?
|
|
508
|
+
|
|
509
|
+
to.print(CLI::UI::ANSI.cursor_up(consumed_lines)) if CLI::UI.enable_cursor?
|
|
510
|
+
while (message = @puts_above.shift)
|
|
511
|
+
to.print(CLI::UI::ANSI.insert_lines(message.lines.count)) if CLI::UI.enable_cursor?
|
|
512
|
+
message.lines.each do |line|
|
|
513
|
+
to.print(CLI::UI::Frame.prefix + CLI::UI.fmt(line))
|
|
514
|
+
end
|
|
515
|
+
to.print("\n")
|
|
516
|
+
end
|
|
517
|
+
# we descend with newlines rather than ANSI.cursor_down as the inserted lines may've
|
|
518
|
+
# pushed the spinner off the front of the buffer, so we can't move back down below it
|
|
519
|
+
to.print("\n" * consumed_lines) if CLI::UI.enable_cursor?
|
|
520
|
+
|
|
521
|
+
true # force full render needed
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
# Render all tasks
|
|
525
|
+
#: (to: io_like, tasks_seen: Array[bool], tasks_seen_done: Array[bool], consumed_lines: Integer, idx: Integer, force_full_render: bool, width: Integer) -> [Integer, Integer]
|
|
526
|
+
def render_tasks(to:, tasks_seen:, tasks_seen_done:, consumed_lines:, idx:, force_full_render:, width:)
|
|
527
|
+
done_count = 0
|
|
528
|
+
|
|
529
|
+
@tasks.each.with_index do |task, int_index|
|
|
530
|
+
nat_index = int_index + 1
|
|
531
|
+
task_done = task.check
|
|
532
|
+
done_count += 1 if task_done
|
|
533
|
+
|
|
534
|
+
if CLI::UI.enable_cursor?
|
|
535
|
+
if nat_index > consumed_lines
|
|
536
|
+
to.print(task.render(idx, true, width: width) + "\n")
|
|
537
|
+
consumed_lines += 1
|
|
538
|
+
else
|
|
539
|
+
offset = consumed_lines - int_index
|
|
540
|
+
move_to = CLI::UI::ANSI.cursor_up(offset) + "\r"
|
|
541
|
+
move_from = "\r" + CLI::UI::ANSI.cursor_down(offset)
|
|
542
|
+
|
|
543
|
+
to.print(move_to + task.render(idx, idx.zero? || force_full_render, width: width) + move_from)
|
|
544
|
+
end
|
|
545
|
+
elsif !tasks_seen[int_index] || (task_done && !tasks_seen_done[int_index])
|
|
546
|
+
to.print(task.render(idx, true, width: width) + "\n")
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
tasks_seen[int_index] = true
|
|
550
|
+
tasks_seen_done[int_index] ||= task_done
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
[done_count, consumed_lines]
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
# Debriefs failed tasks is +auto_debrief+ is true
|
|
557
|
+
#
|
|
558
|
+
# ==== Options
|
|
559
|
+
#
|
|
560
|
+
# * +:to+ - Target stream, like $stdout or $stderr. Can be anything with print and puts methods,
|
|
561
|
+
# or under Sorbet, IO or StringIO. Defaults to $stdout
|
|
562
|
+
#
|
|
563
|
+
#: (?to: io_like) -> bool
|
|
564
|
+
def debrief(to: $stdout)
|
|
565
|
+
@m.synchronize do
|
|
566
|
+
@tasks.each do |task|
|
|
567
|
+
next unless task.done
|
|
568
|
+
|
|
569
|
+
title = task.title
|
|
570
|
+
out = task.stdout
|
|
571
|
+
err = task.stderr
|
|
572
|
+
|
|
573
|
+
if task.success
|
|
574
|
+
next @success_debrief&.call(title, out, err)
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
# exception will not be set if the wait loop is stopped before the task is checked
|
|
578
|
+
e = task.exception
|
|
579
|
+
next @failure_debrief.call(title, e, out, err) if @failure_debrief
|
|
580
|
+
|
|
581
|
+
CLI::UI::Frame.open('Task Failed: ' + title, color: :red, timing: Time.new - @start) do
|
|
582
|
+
if e
|
|
583
|
+
to.puts("#{e.class}: #{e.message}")
|
|
584
|
+
to.puts("\tfrom #{e.backtrace.join("\n\tfrom ")}")
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
CLI::UI::Frame.divider('STDOUT')
|
|
588
|
+
out = '(empty)' if out.nil? || out.strip.empty?
|
|
589
|
+
to.puts(out)
|
|
590
|
+
|
|
591
|
+
CLI::UI::Frame.divider('STDERR')
|
|
592
|
+
err = '(empty)' if err.nil? || err.strip.empty?
|
|
593
|
+
to.puts(err)
|
|
594
|
+
end
|
|
595
|
+
end
|
|
596
|
+
@tasks.all?(&:success)
|
|
597
|
+
end
|
|
598
|
+
end
|
|
599
|
+
end
|
|
600
|
+
end
|
|
601
|
+
end
|
|
602
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'cli/ui'
|
|
5
|
+
|
|
6
|
+
module CLI
|
|
7
|
+
module UI
|
|
8
|
+
module Spinner
|
|
9
|
+
autoload :Async, 'cli/ui/spinner/async'
|
|
10
|
+
autoload :SpinGroup, 'cli/ui/spinner/spin_group'
|
|
11
|
+
|
|
12
|
+
PERIOD = 0.1 # seconds
|
|
13
|
+
TASK_FAILED = :task_failed
|
|
14
|
+
|
|
15
|
+
RUNES = if CLI::UI::OS.current.use_emoji?
|
|
16
|
+
['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'].freeze
|
|
17
|
+
else
|
|
18
|
+
['\\', '|', '/', '-', '\\', '|', '/', '-'].freeze
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
colors = [CLI::UI::Color::CYAN.code] * (RUNES.size / 2).ceil +
|
|
22
|
+
[CLI::UI::Color::MAGENTA.code] * (RUNES.size / 2).to_i
|
|
23
|
+
GLYPHS = colors.zip(RUNES).map { |c, r| c + r + CLI::UI::Color::RESET.code }.freeze
|
|
24
|
+
|
|
25
|
+
class << self
|
|
26
|
+
#: Integer?
|
|
27
|
+
attr_accessor(:index)
|
|
28
|
+
|
|
29
|
+
# We use this from CLI::UI::Widgets::Status to render an additional
|
|
30
|
+
# spinner next to the "working" element. While this global state looks
|
|
31
|
+
# a bit repulsive at first, it's worth realizing that:
|
|
32
|
+
#
|
|
33
|
+
# * It's managed by the SpinGroup#wait method, not individual tasks; and
|
|
34
|
+
# * It would be complete insanity to run two separate but concurrent SpinGroups.
|
|
35
|
+
#
|
|
36
|
+
# While it would be possible to stitch through some connection between
|
|
37
|
+
# the SpinGroup and the Widgets included in its title, this is simpler
|
|
38
|
+
# in practice and seems unlikely to cause issues in practice.
|
|
39
|
+
#: -> String
|
|
40
|
+
def current_rune
|
|
41
|
+
RUNES[index || 0]
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
class << self
|
|
46
|
+
# Adds a single spinner
|
|
47
|
+
# Uses an interactive session to allow the user to pick an answer
|
|
48
|
+
# Can use arrows, y/n, numbers (1/2), and vim bindings to control
|
|
49
|
+
#
|
|
50
|
+
# https://user-images.githubusercontent.com/3074765/33798295-d94fd822-dce3-11e7-819b-43e5502d490e.gif
|
|
51
|
+
#
|
|
52
|
+
# ==== Attributes
|
|
53
|
+
#
|
|
54
|
+
# * +title+ - Title of the spinner to use
|
|
55
|
+
#
|
|
56
|
+
# ==== Options
|
|
57
|
+
#
|
|
58
|
+
# * +:auto_debrief+ - Automatically debrief exceptions or through success_debrief? Default to true
|
|
59
|
+
# * +:to+ - Target stream, like $stdout or $stderr. Can be anything with print and puts methods,
|
|
60
|
+
# or under Sorbet, IO or StringIO. Defaults to $stdout.
|
|
61
|
+
#
|
|
62
|
+
# ==== Block
|
|
63
|
+
#
|
|
64
|
+
# * *spinner+ - Instance of the spinner. Can call +update_title+ to update the user of changes
|
|
65
|
+
#
|
|
66
|
+
# ==== Example Usage:
|
|
67
|
+
#
|
|
68
|
+
# CLI::UI::Spinner.spin('Title') { sleep 1.0 }
|
|
69
|
+
#
|
|
70
|
+
#: (String title, ?auto_debrief: bool, ?to: io_like) { (SpinGroup::Task task) -> void } -> bool
|
|
71
|
+
def spin(title, auto_debrief: true, to: $stdout, &block)
|
|
72
|
+
sg = SpinGroup.new(auto_debrief: auto_debrief)
|
|
73
|
+
sg.add(title, &block)
|
|
74
|
+
sg.wait(to: to)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|