GithubHelp home page GithubHelp logo

cli-ui's Introduction

CLI UI

CLI UI is a small framework for generating nice command-line user interfaces

Installation

gem install cli-ui

or add the following to your Gemfile:

gem 'cli-ui'

In your code, simply add a require 'cli/ui'. Most options assume CLI::UI::StdoutRouter.enable has been called.

Features

This may not be an exhaustive list. Please check our documentation for more information.


Nested framing

To handle content flow (see example below)

CLI::UI::StdoutRouter.enable
CLI::UI::Frame.open('Frame 1') do
  CLI::UI::Frame.open('Frame 2') { puts "inside frame 2" }
  puts "inside frame 1"
end

Nested Framing


Interactive Prompts

Prompt user with options and ask them to choose. Can answer using arrow keys, vim bindings (j/k), or numbers (or y/n for yes/no questions).

For large numbers of options, using e, :, or G will toggle "line select" mode which allows numbers greater than 9 to be typed and f or / will allow the user to filter options using a free-form text input.

CLI::UI.ask('What language/framework do you use?', options: %w(rails go ruby python))

To set the color of instruction text:

CLI::UI::Prompt.instructions_color = CLI::UI::Color::GRAY

Can also assign callbacks to each option

CLI::UI::Prompt.ask('What language/framework do you use?') do |handler|
  handler.option('rails')  { |selection| selection }
  handler.option('go')     { |selection| selection }
  handler.option('ruby')   { |selection| selection }
  handler.option('python') { |selection| selection }
end
  • Note that the two examples provided above are identical in functionality

Interactive Prompt


Free form text prompts

CLI::UI.ask('Is CLI UI Awesome?', default: 'It is great!')

Free form text prompt


Spinner groups

Handle many multi-threaded processes while suppressing output unless there is an issue. Can update title to show state.

CLI::UI::SpinGroup.new do |spin_group|
  spin_group.add('Title')   { |spinner| sleep 3.0 }
  spin_group.add('Title 2') { |spinner| sleep 3.0; spinner.update_title('New Title'); sleep 3.0 }
end

Spinner Group


Text Color formatting

e.g. {{red:Red}} {{green:Green}}

puts CLI::UI.fmt "{{red:Red}} {{green:Green}}"

Text Format


Symbol/Glyph Formatting

e.g. {{*}} => a yellow ⭑

puts CLI::UI.fmt "{{*}} {{v}} {{?}} {{x}}"

Symbol Formatting


Status Widget

CLI::UI::Spinner.spin("building packages: {{@widget/status:1:2:3:4}}") do |spinner|
  # spinner.update_title(...)
  sleep(3)
end

Status Widget


Progress Bar

Show progress of a process or operation.

CLI::UI::Progress.progress do |bar|
  100.times do
    bar.tick
  end
end

Progress Bar


Frame Styles

Modify the appearance of CLI::UI both globally and on an individual frame level.

To set the default style:

CLI::UI.frame_style = :box

To style an individual frame:

CLI::UI.frame('New Style!', frame_style: :bracket) { puts "It's pretty cool!" }

The default style - :box - is what has been used up until now. The other style - :bracket - looks like this:

CLI::UI.frame_style = :bracket
CLI::UI::StdoutRouter.enable
CLI::UI::Frame.open('Frame 1') do
  CLI::UI::Frame.open('Frame 2') { puts "inside frame 2" }
  puts "inside frame 1"
end

Frame Style


Sorbet

We make use of Sorbet in cli-ui. We provide stubs for Sorbet so that you can use this gem even if you aren't using Sorbet. We activate these stubs if T is undefined when the gem is loaded. For this reason, if you would like to use this gem and your project does use Sorbet, ensure you load Sorbet before loading cli-ui.

Example Usage

The following code makes use of nested-framing, multi-threaded spinners, formatted text, and more.

require 'cli/ui'

CLI::UI::StdoutRouter.enable

CLI::UI::Frame.open('{{*}} {{bold:a}}', color: :green) do
  CLI::UI::Frame.open('{{i}} b', color: :magenta) do
    CLI::UI::Frame.open('{{?}} c', color: :cyan) do
      CLI::UI::SpinGroup.new do |sg|
        sg.add('wow') do |spinner|
          sleep(2.5)
          spinner.update_title('second round!')
          sleep (1.0)
        end
        sg.add('such spin') { sleep(1.6) }
        sg.add('many glyph') { sleep(2.0) }
      end
    end
  end
  CLI::UI::Frame.divider('{{v}} lol')
  puts CLI::UI.fmt '{{info:words}} {{red:oh no!}} {{green:success!}}'
  CLI::UI::SpinGroup.new do |sg|
    sg.add('more spins') { sleep(0.5) ; raise 'oh no' }
  end
end

Output:

Example Output

Development

  • Run tests using bundle exec rake test. All code should be tested.
  • No code, outside of development and tests needs, should use dependencies. This is a self contained library

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/Shopify/cli-ui.

License

The code is available as open source under the terms of the MIT License.

cli-ui's People

Contributors

arcadia-rose avatar brunoarueira avatar burke avatar chall8908 avatar cursedcoder avatar darkhole1 avatar davidcornu avatar dependabot-preview[bot] avatar dependabot[bot] avatar donk-shopify avatar expeehaa avatar goodforonefare avatar honkfestival avatar jacobsteves avatar joshheinrichs-shopify avatar jules2689 avatar lavoiesl avatar marianosimone avatar matteodepalo avatar mllemango avatar nicholasellul avatar paulomarg avatar sambostock avatar shanesmith avatar shanet avatar shopify-shipit[bot] avatar t-tonyliang avatar tachyons avatar timothysmith0609 avatar trvrnrth avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cli-ui's Issues

Questions get duplicated when the message is too long

When users answer a question that's too long, the message gets duplicated:

Here's the reproducer:

CLI::UI::Prompt.ask('Super long question that line breaks. What language/framework do you use?') do |handler|
  handler.option('rails')  { |selection| selection }
  handler.option('go')     { |selection| selection }
  handler.option('ruby')   { |selection| selection }
  handler.option('python') { |selection| selection }
end

(it's important to execute it in a small terminal window)

Should gracefully fail when an invalid colour formatter is specified

When an invalid colour is used, the formatter raises an exception and interrupts the workflow. Instead, this should be gracefully handled so the workflow is not interrupted. At most, a warning should be emitted to signal the invalid formatting.

For example:

CLI::UI.fmt("{{grey:this is a grey (gray?) message}}")

Will cause this stack trace:

cli/ui/formatter.rb:113:in `fetch': key not found: "gray" (KeyError)
	 9: from cli-ui/lib/cli/ui.rb:114:in `fmt'
	 8: from cli/ui/formatter.rb:88:in `format'
	 7: from cli/ui/formatter.rb:88:in `each_with_object'
	 6: from cli/ui/formatter.rb:88:in `each'
	 5: from cli/ui/formatter.rb90:in `block in format'
	 4: from cli/ui/formatter.rb:110:in `apply_format'
	 3: from cli/ui/formatter.rb:110:in `each_with_object'
	 2: from cli/ui/formatter.rb:110:in `each'
	 1: from cli/ui/formatter.rb:112:in `block in apply_format'

Documentation of progress percent does not match behaviour.

The Progress component displays "100.0%" no matter what value is passed to the tick method, both of these examples were taken from the documentation and neither one displays properly:

CLI::UI::Progress.progress do |bar|
  20.times do
    sleep 1
    bar.tick(percent: 5)
  end
end
CLI::UI::Progress.progress do |bar|
  tick_amount = 5
  index = 0
  20.times do
    sleep 1
    index += 1
    bar.tick(set_percent: index * tick_amount)
  end
end

[Feature] Multiple Selection Prompt

If possible, I think a multiple selection prompt would be a great addition to the current feature set. When prompt the user for a selection, allow them to select multiple values, perhaps changing their color to show selected/unselected values or have a nice glyph beside the options, and when the selection is finished, return an array of items selected to the developer.

Thanks.

ANSI color code escaping for "ask" broken in Debian

Hi,
I'm trying to debug an issue with the CLI::UI.ask feature not doing ansi color escapes properly on Debian.

Minimal test:

require 'cli/ui'
CLI::UI.ask('Free form input field:')

On debian stable I'm getting this result:

d35f8112e8a1# ruby inputtest.rb
? Free form input field:
[0;94m> [0m[33mUser input goes here
d35f8112e8a1# 

(The [0;94m> [0m[33m should just be a colorized > .)

However, I'm running into some weirdness:
I have this behavior on debian stable, testing and unstable docker images (and on real hardware) but not on the ruby:2.7.4 docker image that is based on debian stable.

Debian stable test:

$ docker run --rm -ti -v $PWD:/test debian /bin/bash
root@2315ddfcaed3:/# cd /test/
root@2315ddfcaed3:/test# apt update -y; apt install ruby -y; gem install cli-ui --no-document
[snip]
Fetching cli-ui-1.5.1.gem
Successfully installed cli-ui-1.5.1
1 gem installed
root@2315ddfcaed3:/test# cat /etc/debian_version 
11.2
root@2315ddfcaed3:/test# ruby --version
ruby 2.7.4p191 (2021-07-07 revision a21a3b7d23) [x86_64-linux-gnu]
root@2315ddfcaed3:/test# ruby inputtest.rb 
? Free form input field:
[0;94m> [0m[33m
root@2315ddfcaed3:/test#

Ruby 2.7.4 image test:

$ docker run --rm -ti -v $PWD:/test ruby:2.7.4 /bin/bash
root@404bad1ba3cc:/# apt update -y; apt dist-upgrade -y; gem install cli-ui --no-document
[snip]
Fetching cli-ui-1.5.1.gem
Successfully installed cli-ui-1.5.1
1 gem installed
root@404bad1ba3cc:/# cd test/
root@404bad1ba3cc:/test# cat /etc/debian_version 
11.2
root@404bad1ba3cc:/test# ruby --version
ruby 2.7.4p191 (2021-07-07 revision a21a3b7d23) [x86_64-linux]
root@404bad1ba3cc:/test# ruby inputtest.rb 
? Free form input field:
> 
root@404bad1ba3cc:/test#

Any ideas on what the cause of this might be and if this is something that a patch to cli-ui would be able to address in the first place?

CLI::UI::Prompt.ask produces non-printable char

CLI::UI::Prompt.ask produces some non-printable character for me. All is normal until an option is selected or the arrow keys are used to change the selection, then a character appears to the left that, when looking very closely, appears to be 0x001B.

I'm using Ubuntu 18.04 with the default gnome-terminal. Will test some other terminals and desktop environments later if that's helpful.

screenshot from 2018-10-11 14-49-10

Have a new gem version published.

The latest published version is v1.3.0 from august 2019. Since then, many changes have been made.
For example, the readme contains code which does not work in v1.3.0 (e.g. CLI::UI.frame_style= does not exist).

Would it be possible to release a new version based on the recent master?

Spinners outside the screen can't update

ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux]
gem version 1.3.0

I have a script that does a lot of downloads, it can do hundreds of downloads in one run depending on the user input. The script itself works great by adding a spinner group for each entry, but when the spinners no longer fit on screen they stop updating (but seemingly still perform their tasks).

The effect can be recreated like this:

require "cli/ui"
CLI::UI::StdoutRouter.enable
sg = CLI::UI::SpinGroup.new

100.times do |i|
  sg.add("Spinner #{i + 1}") do |spinner|
    sleep((i + 1) / 10)
    spinner.update_title("Spinner #{i + 1} done!")
  end
end

sg.wait

If I let it run in a small terminal window, then enlarge the window to fit the spinners that didn't update this is what the output looks like:
screenshot

Why does :options conflict with :default? Would love to see it fixed.

I wonder if there is still a reason why :default is conflicting with :options. I want to rewrite my tool from tty-prompt to cli-ui. I use the |handler| handler.option ... form. I see that the raise was there in the very first commit already but what's the logic behind this limitattion?

wait_for_user_input in lib/cli/ui/prompt/interactive_options.rb raises interupt on left and right inputs

Minimal example to reproduce;

require 'cli/ui'

CLI::UI::Prompt.ask('A or B?') do |handler|
  handler.option('A') { puts 'A' }
  handler.option('B') { puts 'B' }
end

Pressing the left or right arrow keys cause an interrupt to be raised.
Looking at the code it seems to be caught by the else clause in the when :esc_bracket block.

Ideally left and right keypress inputs would be ignored since they're very easy to hit by mistake when navigating.

Should not `ask` when it is not interactive

Shopify-cli insists on asking questions like if sending a failure report when the application is not connected to an interactive terminal, so it just stops working. It should check if it is connected to a terminal before asking questions.

Can I have frames inlined horizontally

I'm trying to build poker console UI using your gem. I need to have some UI boxes aligned horizontally, as I see here there are called "Frames". Is it possible?

ps. Great tool, very simplified :)

Cannot load such file - cli-ui-2.2.0/vendor/reentrant_mutex

Hi there. Nice gem. However, something seems to be broken since one of the latest versions.

The specific error is:

/Users/bikezilla/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/cli-ui-2.2.0/lib/cli/ui/stdout_router.rb:5:in `require_relative': cannot load such file -- /Users/bikezilla/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/cli-ui-2.2.0/vendor/reentrant_mutex (LoadError)

Here's how to reproduce:

→ gem --version
3.4.12
→ ruby -v
ruby 3.2.0 (2022-12-25 revision a528908271) [x86_64-darwin22]
→ which ruby
/Users/bikezilla/.rbenv/shims/ruby
→ gem list | grep cli-ui
→ gem install cli-ui
Fetching cli-ui-2.2.0.gem
Successfully installed cli-ui-2.2.0
Parsing documentation for cli-ui-2.2.0
Installing ri documentation for cli-ui-2.2.0
Done installing documentation for cli-ui after 0 seconds
1 gem installed
→ irb
irb(main):001:0> require 'cli/ui'
/Users/bikezilla/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/cli-ui-2.2.0/lib/cli/ui/stdout_router.rb:5:in `require_relative': cannot load such file -- /Users/bikezilla/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/cli-ui-2.2.0/vendor/reentrant_mutex (LoadError)
        from /Users/bikezilla/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/cli-ui-2.2.0/lib/cli/ui/stdout_router.rb:5:in `<top (required)>'
        from <internal:/Users/bikezilla/.rbenv/versions/3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
        from <internal:/Users/bikezilla/.rbenv/versions/3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
        from /Users/bikezilla/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/cli-ui-2.2.0/lib/cli/ui.rb:381:in `<top (required)>'
        from <internal:/Users/bikezilla/.rbenv/versions/3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:159:in `require'
        from <internal:/Users/bikezilla/.rbenv/versions/3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:159:in `rescue in require'
        from <internal:/Users/bikezilla/.rbenv/versions/3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:39:in `require'
        from (irb):1:in `<main>'
        from /Users/bikezilla/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/irb-1.6.2/exe/irb:11:in `<top (required)>'
        from /Users/bikezilla/.rbenv/versions/3.2.0/bin/irb:25:in `load'
        from /Users/bikezilla/.rbenv/versions/3.2.0/bin/irb:25:in `<main>'
<internal:/Users/bikezilla/.rbenv/versions/3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require': cannot load such file -- cli/ui (LoadError)
        from <internal:/Users/bikezilla/.rbenv/versions/3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
        from (irb):1:in `<main>'
        from /Users/bikezilla/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/irb-1.6.2/exe/irb:11:in `<top (required)>'
        from /Users/bikezilla/.rbenv/versions/3.2.0/bin/irb:25:in `load'
        from /Users/bikezilla/.rbenv/versions/3.2.0/bin/irb:25:in `<main>'

New API for handling options in prompts

When prompting users with options, we often want to handle the result by calling a method.
e.g.

result = CLI::UI.ask('What language/framework do you use?', options: %w(rails go ruby python))
case result
when 'rails'
 ...
when 'go'
 ...
else
 ...
end

This gets really messy with longer options and we end up using hashes

options = {
  'My really really really really really really really really really really long option' => :really_long,
  'My other really really really really really really really really really long option' => :other_option
}
result = CLI::UI.ask('Which option?', options: options.keys)
case options[result]
when :really_long
  ...
when :other_option
  ...
end

This is not great as it requires duplicating constants, pretending hash values are constants, duplicating strings, etc.

Instead, let's make an API that does the following:

CLI::UI.ask('Which option?') do |prompt|
  prompt.option('My Option') { ... }
  prompt.option('My Other Option') { ... }
end

Weird rendering behavior with narrow terminal window

I haven't encountered this myself, but one of my coworkers ran into this the other day. He claims it only happens when his terminal is "very narrow".

Observed behavior:
cli-ui_issue

I'm not sure exactly what's happening here. To do a bit of triage, I asked for the output of IO.console.winsize on a terminal that displays the problem which gave back [50,61]. I tried to replicate on a terminal of the same size, but it seems to work fine for me.

At this point, I'm thinking it's probably something with his specific terminal (iTerm2, I think), but I'm not sure how to go about diagnosing the issue beyond that.

Drawing tables

I searched the documentation for a way to display organized data as columns and rows, aka a 'table' and I could not find any.

Is there any plans to add a dedicated table output similar to the functionality of: https://github.com/tj/terminal-table

It seems it would fall nicely in line with the rest of the framework since it will allow you to organize output in a nice way as well.

Thanks.

Edit: Is there also any plans to incorporating more colors for terminals that have 256 color support, or at least finish the high/low intensity profiles. I noticed you changed blue from 34 to 94, but I think having both forms of all colors would be benefiting if 256 color support is not able to be done.

Make OS detection compatible with JRuby.

I tried using version 1.4 of the gem in one of my projects. This project also uses JRuby for specific reasons, and I don’t intend on changing to MRI.
When requiring the gem, I get the following error:

RuntimeError: Could not determine OS from platform java
  /home/xph/.rvm/gems/jruby-9.2.7.0@myproject/gems/cli-ui-1.4.0/lib/cli/ui/os.rb:15:in `current'
  /home/xph/.rvm/gems/jruby-9.2.7.0@myproject/gems/cli-ui-1.4.0/lib/cli/ui/spinner.rb:13:in `<module:Spinner>'
  /home/xph/.rvm/gems/jruby-9.2.7.0@myproject/gems/cli-ui-1.4.0/lib/cli/ui/spinner.rb:6:in `<module:UI>'
  /home/xph/.rvm/gems/jruby-9.2.7.0@myproject/gems/cli-ui-1.4.0/lib/cli/ui/spinner.rb:5:in `<module:CLI>'
  /home/xph/.rvm/gems/jruby-9.2.7.0@myproject/gems/cli-ui-1.4.0/lib/cli/ui/spinner.rb:4:in `<main>'
  /home/xph/.rvm/gems/jruby-9.2.7.0@myproject/gems/cli-ui-1.4.0/lib/cli/ui.rb:1:in `<module:(root)>'
  /home/xph/.rvm/gems/jruby-9.2.7.0@myproject/gems/cli-ui-1.4.0/lib/cli/ui.rb:18:in `<module:UI>'
  /home/xph/.rvm/gems/jruby-9.2.7.0@myproject/gems/cli-ui-1.4.0/lib/cli/ui.rb:2:in `<main>'
  org/jruby/RubyKernel.java:987:in `require'
  /home/xph/.rvm/gems/jruby-9.2.7.0@myproject/gems/cli-ui-1.4.0/lib/cli/ui.rb:1:in `<main>'
  org/jruby/RubyKernel.java:987:in `require'

This is the place where it fails:

cli-ui/lib/cli/ui/os.rb

Lines 7 to 16 in 3952a78

@current_os ||= case RUBY_PLATFORM
when /darwin/
Mac
when /linux/
Linux
when /mingw32/
Windows
else
raise "Could not determine OS from platform #{RUBY_PLATFORM}"
end

It seemed useful to me to take a look at the ruby constant RUBY_PLATFORM. In JRuby, this is set here to a value in org.jruby.runtime.Constants.PLATFORM, which is set to java (https://github.com/jruby/jruby/blob/f1d8b25818e94500ec914ff79a4bd70fe4237233/core/src/main/resources/org/jruby/runtime/Constants.java#L46).
The failing code in cli-ui does not handle this case and therefore fails.

I do not know, if jruby has an impact on the OS-specific features for which the failing code exists, but I suppose it doesn’t because the features (like emoji support) are probably terminal-related.
Then it would be good to replace RUBY_PLATFORM with something better. For example, there is a gem called os (https://github.com/rdp/os). This takes the host OS information from RbConfig::CONFIG['host_os'], which returns linux for me, even with JRuby. It might be worth it using the same solution for cli-ui. I will probably create a pull request for this.

Spinner does not reset terminal fast enough when there's a lot of output

I'm looking at using this code to install ruby:

CLI::UI::Spinner.spin('Installing ruby') do
  system "brew upgrade ruby-install && ruby-install #{Pathname.pwd.join('.ruby-version').read}"
end

The spinner works as expected initially, but as there's a lot output pretty quickly after that, the title and spinner end up being re-rendered, sometimes there is new text before the title is even rendered. Demo:

Screen.Recording.2021-12-14.at.11.21.20.AM.mov

Handle many multi-threaded processes while suppressing output unless there is an issue.

Based on this comment in the README, I'd expect stdout and stderr to be suppressed.

Cant use gray color option for frame

My code:

require 'cli/ui'

CLI::UI::StdoutRouter.enable
CLI::UI::Frame.open('{{*}}', color: :gray) do
  CLI::UI::Frame.open('КАЛЕНДАРЬ') { puts calendar_info }
  CLI::UI::Frame.open('ПОГОДА') { puts weather_info }
  CLI::UI::Frame.open('ЭНКАУНТЕР') { puts encounter_info }
  CLI::UI::Frame.open('БЫСТРОЕ ПРИКЛЮЧЕНИЕ') { puts adventure_info }
end

Gets me this error:

Снимок экрана 2022-06-16 в 18 14 51

Full error text on paste bin

Error interactive_options.rb:337:in `wait_for_user_input': Interrupt (Interrupt)

When you hit home/end or page-up/page-down cli-ui crashes with this error: interactive_options.rb:337:in `wait_for_user_input': Interrupt (Interrupt). There are more keys that trigger a crash. Shouldn't at least the home/end page-up/page-down navigate options correctly? What is the intended way to handle the keys which cause a crash?

Questions about the Progress Bar widget

if you have:

CLI::UI::Progress.progress do |bar|
      20.times do
        sleep 0.9
        bar.tick(percent: 0.5)
      end
      break
end

And then a Progress Bar right after it, the first one executes normally but then freezes the program; pressing enter just shows the progress bar again at 100%

choosing an option with arrow keys if there's only two options very confusing

E.g.

dev reset-railgun
? ? This project has enabled integrations. Reset data for all?

Displays a choice between yes and no.

It's completely impossible to select an option with arrow keys as it is impossible to know which options is currently selected. One of them is white, the other dark blue. I assumed (wrongly) that the white option was selected.

This could be solved for example by adding a > character in front of the selected option.

Disable the execution duration at the end of the box

Hello guys
Thank you for making this gem available.

How to disable the block execution duration in a box?
For example, removing the (3.2s)

┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ (3.2s) ━━

Thanks!

Add option to allow configuration of ask prompt instructions colour

Currently the ask prompt will output instructions in yellow which may not be desireable as they can detract attention from any warnings that may have been output (which if you are using the warning alias will also be in yellow).

It would be good to be able to configure this (ideally globally, but perhaps also on each call).

Progress bar broken in 2.2?

I'm still working on how/why this happens, but a simple progress bar tick breaks with this backtrace:

/Users/user85540044/.rbenv/versions/3.0.4/lib/ruby/gems/3.0.0/gems/cli-ui-2.2.2/lib/cli/ui/stdout_router.rb:24:in `block in write': undefined method `force_encoding' for #<CLI::UI::Progress:0x00007f87699043c0 @percent_done=1.0, @max_width=157> (NoMethodError) (Excon::Error::Socket)
	from /Users/user85540044/.rbenv/versions/3.0.4/lib/ruby/gems/3.0.0/gems/cli-ui-2.2.2/lib/cli/ui/stdout_router.rb:21:in `map'
	from /Users/user85540044/.rbenv/versions/3.0.4/lib/ruby/gems/3.0.0/gems/cli-ui-2.2.2/lib/cli/ui/stdout_router.rb:21:in `write'
	from /Users/user85540044/.rbenv/versions/3.0.4/lib/ruby/gems/3.0.0/gems/cli-ui-2.2.2/lib/cli/ui/stdout_router.rb:407:in `block in activate'
	from /Users/user85540044/.rbenv/versions/3.0.4/lib/ruby/gems/3.0.0/gems/cli-ui-2.2.2/lib/cli/ui/progress.rb:86:in `print'
	from /Users/user85540044/.rbenv/versions/3.0.4/lib/ruby/gems/3.0.0/gems/cli-ui-2.2.2/lib/cli/ui/progress.rb:86:in `tick'
	from 

Here's my code where it's being triggered.

The ask color change my frame color.

I don't know if this is an issue, or I am doing something wrong. But when I use an ask inside a frame, it changes the frame's color.
Is there an option to set the frame color to an ask?

Expected Behavior

require 'cli/ui'

CLI::UI.frame_style = :bracket
CLI::UI::StdoutRouter.enable
CLI::UI::Frame.open('Frame 1', color: 'blue') do
  CLI::UI.ask('Is CLI UI Awesome?', default: 'It is great!')
  CLI::UI::Prompt.ask('What language/framework do you use?') do |handler|
    handler.option('rails')  { |selection| selection }
    handler.option('go')     { |selection| selection }
  end
end

imagen

Current Behavior

If I use another color on the frame, I can't select the color for the ask, or it is not inherited from the frame to the questions, so I get the next:

require 'cli/ui'

CLI::UI.frame_style = :bracket
CLI::UI::StdoutRouter.enable
CLI::UI::Frame.open('Frame 1', color: 'red') do
  CLI::UI.ask('Is CLI UI Awesome?', default: 'It is great!')
  CLI::UI::Prompt.ask('What language/framework do you use?') do |handler|
    handler.option('rails')  { |selection| selection }
    handler.option('go')     { |selection| selection }
  end
end

imagen

Possible Solution

Add frame_color option to ask?

require 'cli/ui'

CLI::UI.frame_style = :bracket
CLI::UI::StdoutRouter.enable
CLI::UI::Frame.open('Frame 1', color: 'red') do
  CLI::UI.ask('Is CLI UI Awesome?', default: 'It is great!', frame_color: "red")
  CLI::UI::Prompt.ask('What language/framework do you use?',  frame_color: "red") do |handler|
    handler.option('rails')  { |selection| selection }
    handler.option('go')     { |selection| selection }
  end
end

New Gem Version, Please

I manage most of the internal tooling at my current job and some of the other devs I work with have been requesting some of the newer features of cli-ui (specifically filtering). I had thought to just have them override the requested cli-ui by pointing to this repo, but it appears that something might be wrong with the current version on the master branch. Trying to pull directly from GitHub gives a version of 1.2.0, where the current version on RubyGems is 1.2.1.

Granted, I'm being a bit too restrictive with the requested version in some of these cases (>= 1.2.1 isn't really necessary), but I'd also prefer to not have all the devs that want these features pointing their Gemfiles at GitHub anyways - mostly because I doubt they'd remove it once it's not necessary anymore.

So, can has new version?

Add example showing how to run a shell command with stdout redirected

Hi there 👋,

I was playing around with cli-ui and want to two commands in a spingroup. I tried doing this:

CLI::UI::StdoutRouter.enable
sg = CLI::UI::SpinGroup.new
sg.add('A') do
  system("echo 123; exit 1", exception: true)
end
sg.add('B') do
  system("echo 456", exception: true)
end
sg.wait

But then the output is:

456
123
✗ A
✓ B
┏━━ Task Failed: A ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃ RuntimeError: Command failed with exit 1: echo 123; exit 1
┃       from test.rb:127:in `system'
┃       from test.rb:127:in `block in <main>'
┃       from /Users/bouke/.gem/ruby/3.1.1/gems/cli-ui-1.5.1/lib/cli/ui/stdout_router.rb:137:in `block in run'
┃       from /Users/bouke/.gem/ruby/3.1.1/gems/cli-ui-1.5.1/lib/cli/ui/stdout_router.rb:92:in `with_stdin_masked'
┃       from /Users/bouke/.gem/ruby/3.1.1/gems/cli-ui-1.5.1/lib/cli/ui/stdout_router.rb:125:in `run'
┃       from /Users/bouke/.gem/ruby/3.1.1/gems/cli-ui-1.5.1/lib/cli/ui/spinner/spin_group.rb:48:in `block in initialize'
┣━━ STDOUT ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃ (empty)
┣━━ STDERR ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃ (empty)
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ (0.12s) ━━

I want the stdout to be captured in the frame. Since this is probably quite a common use-case, it would be helpful if you could include an example of how to wire up the stdout correctly. I assume it involves doing Open3.popen3 and then 'pumping' the stdout to $stdout yourself so the hooked .write method is called

Unable to run Spinner

Ruby ver: ruby 2.4.1p111
Gem ver: 1.1.0

Whenever I run the example code for a spinner from README, it returns the following error

spin_group = CLI::UI::SpinGroup.new
spin_group.add('Title')   { |spinner| sleep 3.0 }
spin_group.add('Title 2') { |spinner| sleep 3.0; spinner.update_title('New Title'); sleep 3.0 }
spin_group.wait

cliui_error

Other parts work just fine (ex CLI::UI.ask), but it's just spinner that's acting weird 🤔

Spinner test fails indeterminately

Seems that there's a timing issue writing out before in test/dev/ui/spinner_test.rb:75 (test_spinner_error). This fails about 20% of the time:

$ while true; do SEED=28727 ./bin/testunit; [[ $? -ne 0 ]] && break; done
Run options: --seed 28727

# Running:

.........F................................

Finished in 0.989000s, 42.4671 runs/s, 154.7017 assertions/s.

  1) Failure:
Dev::UI::SpinnerTest#test_spinner_error [/Users/mark.campbell/dev-ui/test/dev/ui/spinner_test.rb:75]:
Expected /⠋ broken/ to match "✗ broken".

42 runs, 153 assertions, 1 failures, 0 errors, 0 skips

More succinctly: while true; do ruby -I "test/" ./test/dev/ui/spinner_test.rb; [[ $? -ne 0 ]] && break ; done

Cut new release?

Just noticed that there are quite a lot of commits (and time) since the last tagged release (1.3.0). Any interest in cutting a fresh release with the updates?

Password prompt with CLI::UI.ask

If the current implementation indeed uses gets.chomp, please send me a link to the relevant code. I can add a password: false option that uses getpass from io/console.

[Feature Request] Allow to debrief successful SpinGroups

I'm building a UI in which I want to keep track of processes that can output text (think a command that prints to STDOUT/STDERR). At the end of the process, I'd like to display the output, in a way similar to what SpinGroup.debrief does, but also for non-failed tasks.

Right now this is not possible because of:

next if task.success

It would be great to have something like SpinGroup.failure_debrief and conditionally call it.

Circular dependency warnings

Hi friends 👋 ,

This gem has a few circular dependency issues, Ruby adds a warning about it but this project has disable warning when running the test suite

t.warning = false

Projects depending on cli-ui also have to disabled ruby warnings as otherwise the terminal is cluttered with warning.
Basically all file inside the cli/ui/ folder that contain a require 'cli/ui' will throw a circular dependency warning.

Not a breaking deal, but wanted to let you know :).

multiple options for CLI::UI::Prompt.ask causes error

New to Ruby, so maybe I'm just doing things incorrectly, but this code produces an error:

#!/usr/bin/env ruby

require 'cli/ui'

t_release_instructions = ""

CLI::UI::Prompt.ask('Deployment instructions? Select that all that apply', multiple: true) do |handler|
    handler.option("Migrations") { |selection| selection; t_release_instructions += "- [ ]  Migrations\n" }
    handler.option("New or changed ENV") { |selection| selection; t_release_instructions += "- [ ]  New or changed ENV\n" }
    handler.option("Gem Changes (bundle)") { |selection| selection; t_release_instructions += "- [ ]  Gem Changes (bundle)\n" }
    handler.option("NPM Changes (yarn)") { |selection| selection; t_release_instructions += "- [ ]  NPM Changes (yarn)\n" }
    handler.option("SQL Views") { |selection| selection; t_release_instructions += "- [ ]  SQL Views\n" }
    handler.option("None") { |selection| selection; t_release_instructions = "- None\n" }
end

puts t_release_instructions

Expected, I will see a concatenated string of my selected options outputted.

Actual results, I see this output and error.

? Deployment instructions? Select that all that apply (You chose: Migrations and New or changed ENV)
/Library/Ruby/Gems/2.3.0/gems/cli-ui-1.2.3/lib/cli/ui/prompt/options_handler.rb:19:in `call': undefined method `call' for nil:NilClass (NoMethodError)                                                                                                                                                                                  
Did you mean?  caller                                                                                                                                                                                                                                                                                                                   
        from /Library/Ruby/Gems/2.3.0/gems/cli-ui-1.2.3/lib/cli/ui/prompt.rb:166:in `ask_interactive'                                                                                                                                                                                                                                   
        from /Library/Ruby/Gems/2.3.0/gems/cli-ui-1.2.3/lib/cli/ui/prompt.rb:85:in `ask'                                                                                                                                                                                                                                                
        from ./bin/test.rb:7:in `<main>'       

Using ruby 2.3.7p456 (2018-03-28 revision 63024) [universal.x86_64-darwin18]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.