GithubHelp home page GithubHelp logo

highline's Introduction

HighLine

Tests Gem Version Code Climate Test Coverage Inline docs

Description

Welcome to HighLine.

HighLine was designed to ease the tedious tasks of doing console input and output with low-level methods like gets and puts. HighLine provides a robust system for requesting data from a user, without needing to code all the error checking and validation rules and without needing to convert the typed Strings into what your program really needs. Just tell HighLine what you're after, and let it do all the work.

Documentation

See: Rubydoc.info for HighLine. Specially HighLine and HighLine::Question.

Usage

require 'highline'

# Basic usage

cli = HighLine.new
answer = cli.ask "What do you think?"
puts "You have answered: #{answer}"


# Default answer

cli.ask("Company?  ") { |q| q.default = "none" }

## Disable default value hint showing

my_special_default_object = Object.new

cli.ask("Question?  ") do |q|
  q.default = my_special_default_object
  q.default_hint_show = false
end


# Validation

cli.ask("Age?  ", Integer) { |q| q.in = 0..105 }
cli.ask("Name?  (last, first)  ") { |q| q.validate = /\A\w+, ?\w+\Z/ }

## Validation with custom class
class ZeroToTwentyFourValidator
  def self.valid?(answer)
    (0..24).include? answer.to_i
  end

  def self.inspect
    "(0..24) rule"
  end
end

cli.ask("What hour of the day is it?:  ", Integer) do |q|
  q.validate = ZeroToTwentyFourValidator
end

## Validation with Dry::Types
## `Dry::Types` provides a `valid?` method so it can be used effortlessly

require 'dry-type'

module Types
  include Dry.Types
end

cli.ask("Type an integer:", Integer) do |q|
  q.validate = Types::Coercible::Integer
end

# Type conversion for answers:

cli.ask("Birthday?  ", Date)
cli.ask("Interests?  (comma sep list)  ", lambda { |str| str.split(/,\s*/) })


# Reading passwords:

cli.ask("Enter your password:  ") { |q| q.echo = false }
cli.ask("Enter your password:  ") { |q| q.echo = "x" }


# ERb based output (with HighLine's ANSI color tools):

cli.say("This should be <%= color('bold', BOLD) %>!")


# Menus:

cli.choose do |menu|
  menu.prompt = "Please choose your favorite programming language?  "
  menu.choice(:ruby) { cli.say("Good choice!") }
  menu.choices(:python, :perl) { cli.say("Not from around here, are you?") }
  menu.default = :ruby
end

## Using colored indices on Menus

HighLine::Menu.index_color   = :rgb_77bbff # set default index color

cli.choose do |menu|
  menu.index_color  = :rgb_999999      # override default color of index
                                       # you can also use constants like :blue
  menu.prompt = "Please choose your favorite programming language?  "
  menu.choice(:ruby) { cli.say("Good choice!") }
  menu.choices(:python, :perl) { cli.say("Not from around here, are you?") }
end

If you want to save some characters, you can inject/import HighLine methods on Kernel by doing the following. Just be sure to avoid name collisions in the top-level namespace.

require 'highline/import'

say "Now you can use #say directly"

For more examples see the examples/ directory of this project.

Requirements

HighLine from version >= 3.0.0 requires ruby >= 3.0.0

Installing

To install HighLine, use the following command:

$ gem install highline

(Add sudo if you're installing under a POSIX system as root)

If you're using Bundler, add this to your Gemfile:

source "https://rubygems.org"
gem 'highline'

And then run:

$ bundle

If you want to build the gem locally, use the following command from the root of the sources:

$ rake package

You can also build and install directly:

$ rake install

Contributing

  1. Open an issue
  1. Fork the repository
  1. Clone it locally
  1. Add the main HighLine repository as the upstream remote
  • cd highline # to enter the cloned repository directory.
  • git remote add upstream https://github.com/JEG2/highline
  1. Keep your fork in sync with upstream
  • git fetch upstream
  • git checkout master
  • git merge upstream/master
  1. Create your feature branch
  • git checkout -b your_branch
  1. Hack the source code, run the tests and pronto
  • rake test
  • rake acceptance
  • pronto run
  1. Commit your changes
  • git commit -am "Your commit message"
  1. Push it
  • git push
  1. Open a pull request

Details on:

The Core HighLine Team

For a list of people who have contributed to the codebase, see GitHub's list of contributors.

highline's People

Contributors

abinoam avatar ana06 avatar aregic avatar davispuh avatar elyscape avatar fissionxuiptz avatar fredrb avatar iconoclast avatar jeg2 avatar kachick avatar kbrock avatar km4n avatar koic avatar krausefx avatar lachlan avatar matugm avatar mmihira avatar mnzaki avatar olleolleolle avatar petergoldstein avatar practicingruby avatar presidentbeef avatar rleber avatar roniegh avatar sax avatar stepheneb avatar stomar avatar whiteleaf7 avatar yazgoo avatar zzzzou 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

highline's Issues

Need instructions for building gem

The install instructions show how to install the gem (from rubyforge) or by using setup.rb, but not how to build the gem from source. Can you add this?

Highline v1.6.2 Error

Hi James,

I was working on a chef setup with vagrant and hit a wall with it dying on https://github.com/JEG2/highline/blob/master/lib/highline.rb#L711

chef] Destroying VM and associated drives...
[chef] Running cleanup tasks for 'chef_solo' provisioner...
/Users/mdesilva/.vagrant.d/gems/gems/highline-1.6.20/lib/highline.rb:711:in `format_statement': undefined method `to_str' for {"chef-server"=>"2.0.0"}:Hash (NoMethodError)
    from /Users/mdesilva/.vagrant.d/gems/gems/highline-1.6.20/lib/highline.rb:617:in `say'

I've 'patched' it locally by hand by changing to_str to to_s.

ffi-ncurses requires libXCurses under JRuby 1.5

If I run
jruby -e 'require "rubygems"; require "ffi-ncurses"'

under JRuby 1.4.0 with a system that has libncurses installed but not XCurses, I get no error. If I run it under JRuby 1.5.0.RC1 I get:

jruby-1.5.0.RC1/lib/ruby/site_ruby/shared/ffi/library.rb:28:in ffi_lib': Could not open library 'XCurses' : ld.so.1: java: fatal: XCurses: open failed: No such file or directory. Could not open library 'libXCurses.so' : ld.so.1: java: fatal: libXCurses.so: open failed: No such file or directory (LoadError) from jruby-1.5.0.RC1/lib/ruby/site_ruby/shared/ffi/library.rb:10:inmap'
from jruby-1.5.0.RC1/lib/ruby/site_ruby/shared/ffi/library.rb:10:in ffi_lib' from jruby-1.5.0.RC1/lib/ruby/gems/1.8/gems/ffi-ncurses-0.3.2/lib/ffi-ncurses.rb:25 from jruby-1.5.0.RC1/lib/ruby/gems/1.8/gems/ffi-ncurses-0.3.2/lib/ffi-ncurses.rb:36:inrequire'
from jruby-1.5.0.RC1/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36:in `require'
from -e:1

line 25 is:

  LIB_HANDLE = ffi_lib( 'ncurses', 'libncurses.so.5', 'XCurses' ).first

this seems to have to do with a change in how ffi_lib behaves with multiple arguments. See

http://groups.google.com/group/ruby-ffi/browse_thread/thread/11b365ae7374c20d/3856ede8fe72ead3?lnk=raot

JRuby 1.7

I'm trying to use highline on JRuby 1.7 (jruby-head with rvm) and it fails with:
NameError: cannot load Java class jline.ConsoleReader

conflict between HighLine and Mechanize

I'm not really sure what's happening here:

#!/usr/bin/env ruby -w

require 'rubygems'
require 'mechanize'
require 'highline'
require 'highline/import'

WWW::Mechanize.new.get "http://gooogle.com"
ask "wha?"

yields:

wha?
/Library/Ruby/Gems/1.8/gems/highline-1.5.1/lib/highline.rb:603:in `get_line': The input stream is exhausted. (EOFError)
    from /Library/Ruby/Gems/1.8/gems/highline-1.5.1/lib/highline.rb:624:in `get_response'
    from /Library/Ruby/Gems/1.8/gems/highline-1.5.1/lib/highline.rb:218:in `ask'
    from /tmp/foo.rb:7

I'm at a loss here :(

echo != true fails in presence of termios

To reproduce:

ruby -rhighline -e 'p [HighLine::VERSION, defined?(Termios)]; HighLine.new.ask("foo: ") { |q| q.echo = false }'
["1.6.14", "constant"]
foo: You must enter a valid HighLine::String.
?  You must enter a valid HighLine::String.
?  You must enter a valid HighLine::String.
^C

The offending change is 2abb2c7; all occurrences of input in raw_no_echo_mode and restore_mode in the "termios" branch should probably be replaced with @input.

echo=false with jruby clears terminal

When using highline under jruby (with ffi-ncurses) on Linux I get this weird behavior that highline clears the terminal before allowing me to enter characters in echo=false mode:

!/usr/bin/env ruby

require 'rubygems'
require 'highline/import'

ask("Username ?\n")
ask("Password ?\n") { |q| q.echo = false }

The environment is:

$ ruby -v
jruby 1.6.4 (ruby-1.8.7-p330) (2011-08-23 17ea768) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_26) [linux-amd64-java]

$ gem list

*** LOCAL GEMS ***

ffi (1.0.9 java)
ffi-locale (1.0.1)
ffi-ncurses (0.4.0)
highline (1.6.8)

HighLine::SystemExtensions::CHARACTER_MODE is 'ncurses'.

echo = false clears terminal

require "highline/import"

pass = ask("Password: ") { |q| q.echo = false }

Ruby:
ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-linux]

Gems:
ffi (1.0.11)
ffi-locale (1.0.1)
ffi-ncurses (0.4.0)
highline (1.6.13)

HighLine::SystemExtensions::CHARACTER_MODE == "ncurses"

Similar to #22, but on standard Ruby interpreter.

Bump Version on rubygems.org

Can you push the latest version (1.6.5) to rubygems? I depend on the new bright color support and would prefer not having to build it from Github.

UTF-8 charaters in menu.prompt and choice fail

When using UTF-8 characters in the menu block, non-ASCII characters only appear as question marks. Encoding an all strings is "UTF-8". I am using Win7 with ruby 1.9.3p125 and highline 1.6.15.

# encoding: UTF-8

require "highline/import"

puts "äöüß©¶¼"
say "äöüß©¶¼"

choose do |menu|
  menu.prompt = "äöüß©¶¼"
  menu.choice "äöüß©¶¼" do end
end

The output is:

äöüß©¶¼
äöüß©¶¼
1. ??????????????
??????????????

Ambiguous choice.  Please choose one of ["1", "\u00E4\u00F6\u00FC\u00DF\u00A9\u00B6\u00BC"].

encoding infos?

Not sure that this is an issue but i'm having problems with character encoding an page wrap function...

I'm trying to wrap a text that contains non us-ascii characters...

in ruby 1.8 everything works fine but in 1.9.1 i'm having this issue:

/usr/local/rvm/gems/ruby-1.9.1-p378/gems/highline-1.6.1/lib/highline.rb:733:in `block in wrap': invalid byte sequence in US-ASCII (ArgumentError)

I'm now really a ruby-utf master so probably this is just all my fault but i would appreciate an hint if you have the time :)

thanks

Ghedamat

p.s.
I LOVE this gem!

Highline is not detecting the ffi-ncurses lib in Jruby

$ jruby -S gem install ffi-ncurses
Successfully installed ffi-ncurses-0.3.2
1 gem installed
Installing ri documentation for ffi-ncurses-0.3.2...
Installing RDoc documentation for ffi-ncurses-0.3.2...

$ jruby -S cap deploy

*** Using highline effectively in JRuby requires manually installing the ffi-ncurses gem.
*** jruby -S gem install ffi-ncurses
...

Problem with:: highline with capistrano on Windows

I'm getting this error after using the command "cap staging deploy" and I'm not sure what is going on! Propably something is broken on my windows but I'm not sure what it could be. Could you help me ?

C:/Ruby187/lib/ruby/gems/1.8/gems/highline-1.6.19/lib/highline/system_extensions.rb:81: undefined method dlload' for HighLine::SystemExtensions::WinAPI:Module (N oMethodError) from C:/Ruby187/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:29:ingem_original_require'
from C:/Ruby187/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:29:in require' from C:/Ruby187/lib/ruby/gems/1.8/gems/highline-1.6.19/lib/highline.rb:14 from C:/Ruby187/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:29:ingem_original_require'
from C:/Ruby187/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:29:in `require'

Release new version 1.6.21

It's quite a long time since 1.6.20 and you already merged few PRs. Time for releasing a new version maybe?

get_character waits for `Enter'

The following does not work as expected, it requires the 'Enter' key to be pressed. A couple of months ago it worked just fine.
Update: This regression was introduced with version 1.6.14.

require 'highline/system_extensions'
input = HighLine::SystemExtensions.get_character

ruby 1.9.3p194 (2012-04-20 revision 35410) [i686-linux]
highline (1.6.15)
stty 8.13

(termios library not installed)

Backspace not working

Environment:

  • jruby 1.6.5 (ruby-1.8.7-p330) (2011-10-25 9dcd388) (Java HotSpot(TM) Client VM 1.6.0_21) [Windows XP-x86-java]
  • highline (1.6.5)

Scenario:

irb(main):001:0> require 'rubygems'
=> true
irb(main):002:0> require 'highline/import'
=> true
irb(main):003:0> ask("Password:  ") { |q| q.echo = "*" }
Password:  *****
=> "12345"
irb(main):004:0> ask("Password:  ") { |q| q.echo = "*" }
Password:  *****You must enter a valid HighLine::String.
?
=> ""

Line 3 prompts for a password and "12345" is entered. It works as expected.
Line 4 prompts for a password and "12345" followed by a "backspace" is entered. Highline responds with an error "You must enter a valid HighLine::String".

Claus

release new version.

please release new version. I saw that unicode issue fixed in master branch. tnx

Please make HighLine beautiful like Yeoman

I discovered Yeoman recently and I'm really impressed by their terminal interface. Yeowman is a scaffold generator similar to "rails generate", but it's general-purpose and written in JavaScript. Their terminal interface:

  • ...use colors.
  • ...support arrow keys.
  • ...rewrite prompts after the user has answered, to make it look more beautiful.
  • ...is not restricted to printing text up to down. For example their menu interface moves the cursor using the arrow keys.

I feel very good when using Yeoman's interface. I had the feeling that it's very user friendly. I want my users to feel good as well when using my software's interface. So it would be really great if you can make HighLine beautiful as Yeoman.

It's really hard to explain Yeoman's interface. I've posted a screenshot here that gives you some idea of how it works, but for the full experience you should really try it out yourself.

screen shot 2013-12-11 at 10 47 58

For example, when asking for permission to track usage, it first displays a regular Y/n prompt:

====: (Y/n)

Then when you answer "Y", the (Y/n) is erased and replaced with a colored Yes string, as the one you see in the screenshot.

When asking which modules to choose, the menu there actually supports the arrow keys! You can press Up and Down, and the menu chooser arrow will go up and down, and the text "Press to select" will disappear. When you press space, the filled bullet will become a hollow bullet.

These kinds of subtle things make the terminal feel modern again.

Yeoman uses the Inquirer library for implementing most of its interface. Inquirer is a bit like HighLine. Under the hood, Inquirer uses cli-color for terminal color formatting and basic cursor moving, and readline for text prompts.

Object Oriented Menus Proposal

Hi,
I just wanted to touch base and see if the following functionality would be approved as a patch to this code base as I am planning to code it regardless and I want to gear it towards either being plugged directly into Highline or being its own add-on gem. (If the former is possible, I think it's important I talk to you guys beforehand to ensure I meet whatever constraints you want to impose.)

Basically, I want to code a way for something like this (input/output from use of 'checkinstall' menu editor) as the end result, but on the way there, a lot of features could easily be added that I think could make highline a bit more robust than it already is, for instance with wizards/workflows to fully describe the variables to be set in a class. Here's the screenshot:
Checkinstall Menu Editor

Basically:
I want the ability to see all the values for an object at a glance and be able to set any one of them individually. (If this is done, it's an insignificant amount of work to have the added feature of prompting for each value in sequence.) The only thing that this screenshot doesn't show that I'd like is the ability to abort changing a field, and also to re-set it to the default value.

I think the way I want to implement this is to accept classes that have some sort of ActiveModel-type class interface (though I would want this to be agnostic in terms of dependencies or the model's inhereted attributes, so I would just expect the provided class to respond to certain functions).

The benefit of this, is if "include Highline::Model" is added to the model, we can design our own methods like Model.wizard or Model.menu that could be called on it.

Any model would only need to have the following functionality defined:

  • A method returning list of the attributes to be set.
  • A method to set a given attribute to a given value.

We could additionally accept, but not require, the following methods to that model for more advanced features: (Say the column in question is 'name'.)

  • #name_default -- will show up between square brackets at the prompt and will be assumed as the answer if no input is provided.
  • #name_hide? -- will make an attribute /not/ appear either for the wizard, each redraw of the menu or both (depending on return value), if, for instance, a specific answer to another value has rendered the choice moot.
  • Compatibility with include ActiveModel::Validations for validations or a custom-implemented model with a similar interface. For instance, #name_validates? could be called on setting any attribute to accept/reject the value and, if accepted, #validate could be called on the record after any attribute is changed for the purpose of obtaining an array of warnings/errors for the console to list if any attributes are incompatible with each other.
  • Compatibility with the 'simple_enum' gem (or similar custom implementation). This would turn any field into an enumerated list of choices rather than free-response-type input.
  • Compatibility with 'ActiveAttr' gem (or similar implementation) for typecasting (and setting default values).
  • Compatibility with ActiveModel::SecurePassword (for instance by not echoing input when taking values for this field.)
  • Compatibility with ActiveModel::Dirty (for instance by selectively showing the save button).

Please let me know what you guys think.

UnevenColumnsAcross doesn't take color into account

From #14:

This patch seems to work fine in the usual case.

ruby-1.9.2-p180 :007 > a = %w(Blah a b c ad e fs f g)
 => ["Blah", "a", "b", "c", "ad", "e", "fs", "f", "g"] 
ruby-1.9.2-p180 :008 > puts ui.list(a, :uneven_columns_across, 3)
Blah  a   b
c     ad  e
fs    f   g
 => nil 

However, when there's bold formatting on the first row, it doesn't seem to work right:

ruby-1.9.2-p180 :009 > a = [ui.color("Blah", :bold), ui.color("a", :bold), ui.color("b", :bold), "c", "ad", "e", "fs", "f", "g"]
 => ["\e[1mBlah\e[0m", "\e[1ma\e[0m", "\e[1mb\e[0m", "c", "ad", "e", "fs", "f", "g"] 
ruby-1.9.2-p180 :010 > puts ui.list(a, :uneven_columns_across, 3)
Blah  a  b
c             ad         e        
fs            f          g        
 => nil 

One specific use case for this issue is the knife-rackspace library. Example.

Add the GemSpec to Git

Please add the highline.gemspec to git, to make it easy to add a dependency on highline with a git source to a Gemfile and to make it standard to install a checkout from the command line.

ffi-ncurses warning persists on JRuby even after installed.

I will look into this issue soon, but archiving for now.

$ irb
>> require "rubygems"
=> true
>> require "highline"

*** Using highline effectively in JRuby requires manually installing the ffi-ncurses gem.
*** jruby -S gem install ffi-ncurses
=> true
>> exit
anatta:~ seacreature$ gem list ffi-ncurses

*** LOCAL GEMS ***

ffi-ncurses (0.3.2)

HighLine.new.ask("Q?"){|q| q.overwrite = true} errors with version 1.6.5

Running gem version 1.6.5 under Ruby 1.9.2 I encounter this:

require 'highline'
answer = HighLine.new.ask("Password:"){|q| q.overwrite = true ; q.echo = '*'}

Result:
Password:
**********You must enter a valid HighLine::String.

The code worked just fine in previous versions, returning the user's input. If I omit the q.overwrite=true part, it works. So something has changed in the overwrite code path that breaks HighLine.

Thanks.

Aaron Gifford

password still showing

I'm using this code from the examples: ask("Enter your password: ") { |q| q.echo = "x" }

The problem is my output looks like this:
Screen Shot 2013-04-04 at 10 09 38 AM

Before I updated because of the annoying warning telling me to use Fiddle instead of DL, this code worked fine (I'm on Windows 7).

Please help.

repeat_entry.rb example's hash gather repeats the original question twice, not using elements of the hash

Cut down code from examples/repeat_entry.rb

require 'rubygems'
require 'highline/import'
pass = ask("Enter your password:  ") do |q|
  q.echo = '*'
  q.verify_match = true
  q.gather = {"Enter a password" => '',
              "Please type it again for verification" => ''}
end

response from terminal:

Enter your password:  ****
// I expected: "Enter a password: "
Enter your password:  ****      
// I expected: "Please type it again for verification: "
Your password is now asdf!

I feel like I might be missing something in terms of usage that isn't correctly illustrated by the example.

Ambiguous choice doesn't display options properly.

When given a menu, and the user chooses an incorrect response, the message displayed doesn't list the options.

irb(main):004:0> hl.choose(:a,:b,:c)
1. a
2. b
3. c
?            # I pressed enter without making a choice
Ambiguous choice.  Please choose one of [].
?  6
You must choose one of [].
?

Surprising behavior for character = true resp. character = :getc with stty

I am trying to get a single character from the user in a "cleaner" way than with SystemExtensions.get_character, which is not well documented and feels rather like a hack to me (see also issue #50).

While playing around with the echo and character settings, I stumbled over two issues(?):

  1. The documentation is not very clear (at least to me) about the difference between character = true and character = :getc. When to choose which? Are they supposed to behave differently or is this only an implementation detail?
  2. I do not understand the behavior of character = true in the example code below (newline and indentation; examples one and three behave as expected).

Output:

Your password?
password: 12345
Answer [ynaq]?
               key: q (character = true)
Answer [ynaq]? key: q (character = :getc)

Code:

require 'rubygems'
require 'highline/import'

answer = ask("Your password? ") do |q|
           q.echo = false
         end
puts "password: #{answer}"

key = ask("Answer [ynaq]? ") do |q|
        q.echo = false
        q.character = true
      end
puts "key: #{key} (character = true)"

key = ask("Answer [ynaq]? ") do |q|
        q.character = :getc
      end
puts "key: #{key} (character = :getc)"

gather attribute does not work with menu

The RDoc says to use the gather attribute of a Question to select multiple items. This works when using ask, but it fails when using choose. This seems odd since Menu (passed to the choose block) inherits from Question (passed to the ask block)

This code

#!/usr/bin/env ruby

require 'highline/import'
require 'rb-readline'

choices = %w[ rabbit caterpillar frog ]

x = choose do |menu|
  menu.prompt = "Animal?  "
  menu.choices(*choices)
  menu.gather = 3
end

generates, after entering three choices, this error:

/Users/seanmackesey/.rvm/gems/ruby-1.9.3-p194/gems/highline-1.6.15/lib/highline/menu.rb:303:in `[]': no implicit conversion from nil to integer (TypeError)

It seems like menu should work with gather. Is it not intended to? You also get an error if you set gather to a string/regexp.

1.9.1 ask - echo delayed, buffer not flushed

This Ruby snippet has two problems:
h = HighLine.new
pw1 = h.ask("Enter password one") {|q| q.echo = ''}
pw2 = h.ask("Enter password two") {|q| q.echo = '
'}
print "\npw1=#{pw1} pw2=#{pw2}"

  1. Echoed asterisks are delayed until Enter is pressed
  2. User does not get a chance to enter password two - pw2 is ""

This workaround - extra calls to h.ask - solves problem (2):
h = HighLine.new
pw1 = h.ask("Enter password one") {|q| q.echo = ''}
h.ask(" ")
pw2 = h.ask("Enter password two") {|q| q.echo = '
'}
h.ask(" ")
print "\npw1=#{pw1} pw2=#{pw2}"

highline (1.5.1)
ruby 1.9.1p0 (2009-01-30 revision 21907) [i386-mswin32]
Windows XP Pro SP 3

The input stream is exhausted

I am trying to test the output from the Terminal and wrote this snippet that narrows down what I am trying to do. https://gist.github.com/1474931. Would you be able to tell me if I am testing HighLine incorrectly?

I see that calling Readline.readline(question, true) results in a nil return value. At that point of execution, question is defined as @output.string which is equal to the empty string "". Now, if I'm testing the output text, why am I getting an error relating to the input?

I am running Ruby 1.9.2-p290 with the latest version of highline on the latest version of Mac OS X.

Incidentally, I tried the same test on a Windows 7 machine with Ruby 1.9.3-p0 and got the following results:

C:\Users\ddyba\Scripts\exhausted_input>ruby highline_test.rb
Run options:

# Running tests:

E

Finished tests in 0.005000s, 200.0000 tests/s, 0.0000 assertions/s.

  1) Error:
test_ask_question_returns_prompt(HighLineTest):
NoMethodError: private method `puts' called for nil:NilClass
    C:/Users/ddyba/.pik/rubies/Ruby-193-p0/lib/ruby/gems/1.9.1/gems/highline-1.6.8/lib/highline.rb:608:in `say'
    C:/Users/ddyba/.pik/rubies/Ruby-193-p0/lib/ruby/gems/1.9.1/gems/highline-1.6.8/lib/highline.rb:245:in `ask'
    highline_test.rb:7:in `ask_question'
    highline_test.rb:15:in `setup'

1 tests, 0 assertions, 0 failures, 1 errors, 0 skips

C:\Users\ddyba\Scripts\exhausted_input>

Some test failures on Windows

All test passes on MacOSX.
But some failures on Windows.

Environment(Windows)

  • Windows7 64bit
  • ruby 1.9.3p362 (2012-12-25) [i386-mingw32]
  • Head(e785e6e)
p HighLine::SystemExtensions::CHARACTER_MODE #=> "Win32API"

TestResult

Finished tests in 0.359375s, 256.0000 tests/s, 2148.1739 assertions/s.

  1) Failure:
test_backspace_does_not_enter_prompt(TestHighLine) [E:/GitHub/highline/test/tc_highline.rb:158]:
<""> expected but was
<"\b\b">.

  2) Failure:
test_character_echo(TestHighLine) [E:/GitHub/highline/test/tc_highline.rb:136]:
<"Please enter your password:  ********\n"> expected but was
<"Please enter your password:  *********\n">.

92 tests, 772 assertions, 2 failures, 0 errors, 0 skips

Note

An warning occured.

Warning:C:/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36: Win32API is dep
recated after Ruby 1.9.1; use dl directly instead

highline 1.6.9 fails tests

With ruby 1.8.7 (2011-12-28 patchlevel 357) [x86_64-linux] I get several test failures. I'm only including the first, all the others also have the same TypeError. Tests all pass for highline 1.6.8.

  1) Error:
test_backspace_does_not_enter_prompt(TestHighLine):
TypeError: wrong argument type StringIO (expected File)
    ./lib/highline/system_extensions.rb:74:in `getattr'
    ./lib/highline/system_extensions.rb:74:in `get_character'
    ./lib/highline.rb:800:in `get_single_character'
    ./lib/highline.rb:833:in `get_response'
    ./lib/highline.rb:262:in `ask'
    ./test/tc_highline.rb:147:in `test_backspace_does_not_enter_prompt'

HighLine#say doesn't handle colorized strings correctly

The original HighLine#say method will correctly not emit a newline with the statement (displaying with print and flush) when it ends in whitespace. However, if one creates a string ending in whitespace and then uses HighLine#color to colorize it, HighLine#say will emit the newline, which is rarely-if-ever the intended behavior. I have modified the method to cause it to print and flush (no newline) when the statement string ends with whitespace directly preceding a color code, by way of a regex.

requiring highline is very slow

Simply adding require 'highline' to an app results in 44k calls to Symbol#to_s and over 30k calls to String#==

$ ruby -r profile -e 'require "highline"'
  %   cumulative   self              self     total
 time   seconds   seconds    calls  ms/call  ms/call  name
 30.21     0.29      0.29      354     0.82     1.13  Array#map
 20.83     0.49      0.20      359     0.56     0.72  Array#include?
 11.46     0.60      0.11    44286     0.00     0.00  Symbol#to_s
  6.25     0.66      0.06    30382     0.00     0.00  String#==

This is quite a bit of overhead for a small cli tool.

Regression in answer_type conversion

I believe that commit f853f4a broke the following test case that worked in release 1.6.2 and is broken in 1.6.5 and later.

  def test_ask_string
    name = "James Edward Gray II"
    @input << name << "\n"
    @input.rewind

    assert_equal(name, @terminal.ask("What is your name?  ", String))

    assert_raise(EOFError) { @terminal.ask("Any input left?  ", String) }
  end

The error that I am getting is

NoMethodError: undefined method `parse' for String:Class
    /home/jsman/code/highline/lib/highline/question.rb:329:in `convert'
    /home/jsman/code/highline/lib/highline.rb:268:in `ask'
    /home/jsman/code/highline/test/tc_highline.rb:70:in `test_ask_string'

HighLine#ask crashes on suspend

If the user suspends the program while being HighLine#ask'ed a question, HighLine occasionally crashes. Ideally, suspending (i.e. SIGSTOP) should be supported.

Edit CHANGELOG?
^Z
[1]  + 39240 suspended  rake release
➜  myproject git:(master) git tag -l
➜  myproject git:(master) fg
[1]  + 39240 continued  rake release
rake aborted!
Input/output error - <STDIN>
/Users/mickeyreiss/.rvm/gems/ruby-1.9.3-p448@myproject/gems/highline-1.6.20/lib/highline.rb:863:in `eof?'
/Users/mickeyreiss/.rvm/gems/ruby-1.9.3-p448@myproject/gems/highline-1.6.20/lib/highline.rb:863:in `get_line'
/Users/mickeyreiss/.rvm/gems/ruby-1.9.3-p448@myproject/gems/highline-1.6.20/lib/highline.rb:885:in `get_response'
/Users/mickeyreiss/.rvm/gems/ruby-1.9.3-p448@myproject/gems/highline-1.6.20/lib/highline.rb:260:in `ask'
/Users/mickeyreiss/.rvm/gems/ruby-1.9.3-p448@myproject/gems/highline-1.6.20/lib/highline.rb:223:in `agree'
/Users/mickeyreiss/code/myproject/Rakefile:47:in `block in <top (required)>'
Tasks: TOP => release
(See full trace by running task with --trace)

OS X 10.8.4/zsh 4.3.11

choose prints "Ignored" instead of choices on JRuby

taking the example from examples/menus.rb

require "rubygems"
require "highline/import"

choose do |menu|
  menu.prompt = "Please choose your favorite programming language?  "

  menu.choice :ruby do say("Good choice!") end
  menu.choices(:python, :perl) do say("Not from around here, are you?") end
end

in MRI 1.9.3, this behaves as expected

1.9.3p194 :001 > require "rubygems"
 => false 
1.9.3p194 :002 > require "highline/import"
 => true 
1.9.3p194 :003 > 
1.9.3p194 :004 >   choose do |menu|
1.9.3p194 :005 >       menu.prompt = "Please choose your favorite programming language?  "
1.9.3p194 :006?>   
1.9.3p194 :007 >       menu.choice :ruby do say("Good choice!") end
1.9.3p194 :008?>     menu.choices(:python, :perl) do say("Not from around here, are you?") end
1.9.3p194 :009?>   end
1. ruby
2. python
3. perl
Please choose your favorite programming language?  1
Good choice!
 => nil 

not so much in JRuby 1.7.0

jruby-1.7.0 :001 > require "rubygems"
 => false 
jruby-1.7.0 :002 > require "highline/import"
 => true 
jruby-1.7.0 :003 > 
jruby-1.7.0 :004 >   choose do |menu|
jruby-1.7.0 :005 >       menu.prompt = "Please choose your favorite programming language?  "
jruby-1.7.0 :006?>   
jruby-1.7.0 :007 >       menu.choice :ruby do say("Good choice!") end
jruby-1.7.0 :008?>     menu.choices(:python, :perl) do say("Not from around here, are you?") end
jruby-1.7.0 :009?>   end
Ignored

Ambiguous choice.  Please choose one of ["1", "2", "3", :ruby, :python, :perl].
?  Ignored

Ambiguous choice.  Please choose one of ["1", "2", "3", :ruby, :python, :perl].
?  Igno1

Good choice!
 => nil 

any ideas?

thanks!
Andras

ps: i'm on 1.6.15

Output is not shown when calling say

Hello,

I have seen a problem when i am calling another ruby program from mine using the backquotes `. And the problem is that the infos that are display with the say method are not echoed back in my terminal.

The gem that i'm trying to call is shezen, and during the build process they sometimes "say" some things that i want to see in my terminal.

ipa build -c Release

Can you help figure out why it is not displayed ?

terminal_size return nil in some environments in Linux

Hi,
In some environments on Linux, stty returns an empty string, which means that terminal_size returns nil instead of integers. This causes test_terminal_size test in test/tc_highline.rb, line 932 to fail.

Examples of such environments are the clean environment created by pbuilder and sbuild in Debian to build packages. It probably can happen on other occasions.

If you want to insist on terminal size to return Fixnums, should terminal_size return a size of 0 if stty cannot return the size of the terminal?

Cheers,

Cédric

JRuby: ::HighLine::SystemExtensions::terminal_size raises exception

Works as expected in 1.9.3

$ rvm use 1.9.3
$ irb
1.9.3p194 :001 > require 'highline'
 => true 
1.9.3p194 :002 > ::HighLine::SystemExtensions::terminal_size

JRuby doesn't seem to like it

$ rvm use jruby
$ irb
irb(main):001:0> require 'highline'
=> true
irb(main):002:0> ::HighLine::SystemExtensions::terminal_size
NoMethodError: undefined method `getTerminalWidth' for nil:NilClass
    from /Users/neilmatatall/.rvm/gems/jruby-1.7.1/gems/highline-1.6.15/lib/highline/system_extensions.rb:121:in `terminal_size'
    from (irb):2:in `evaluate'
    from org/jruby/RubyKernel.java:1066:in `eval'
    from org/jruby/RubyKernel.java:1392:in `loop'
    from org/jruby/RubyKernel.java:1174:in `catch'
    from org/jruby/RubyKernel.java:1174:in `catch'
    from /Users/neilmatatall/.rvm/rubies/jruby-1.7.1/bin/irb:13:in `(root)'

This came up in presidentbeef/brakeman#229

Allow menu lines to be customized beyond the index

HighLine::Menu feels relatively restricted. Besides the index, the output of each line can only contain the item.

This means that where you have simple items and more descriptive textual forms you end up stuck only outputting the cryptic short item leaving you with a not so intuitive user interface.

For example take a list of countries. With (item, text) pairs like (:us, "United States"), (:ca, "Canada"), ... the interface is stuck looking like this:

1. us
2. ca
Country: us

Since we have textual forms a much more intuitive way to output this menu would be:

1. us - United States
2. ca - Canada
Country: us

However this is currently impossible without reimplementing the layout in a really mess and hacky way. Menu has help text however all this does when used is add an additional help item which isn't very useful or intuitive for this.

highline 1.6.9 hangs indefinitely with JRuby

With jruby 1.5.6 (ruby 1.8.7 patchlevel 249) (2012-01-08 6586) (OpenJDK 64-Bit Server VM 1.6.0_22) [amd64-java] tests hang indefinitely. I've tested both with and without your patch for my ruby 1.8 bug. It shows two dots when running its tests and then hangs. I realize that our jruby is old but we can't currently upgrade since 1.6 versions don't run properly on our system.

HighLine#list formats columns too wide

HighLine#list in :columns_across mode makes each column at least as wide as the widest element in any column.

> list = %w(1 2 3 4 a b c d asdf1234 f g h)
> puts HighLine.new.list(list, :columns_across, 4)
1         2         3         4
a         b         c         d
asdf1234  f         g         h
 => nil

Some tables may have a single wide column (maybe 1/4-1/2 the screen) and many narrow columns. The method above is may work for a few columns of similar max widths, but it doesn't work very well for lists having a single wide column and many narrow columns.

Instead, this method should make each column as wide as the widest element found in that column only. As an example, the widest element in columns[0] has width 8, so the width of columns[0] overall should be 8 + padding. The widest element in columns[1] has width 1, so the width of columns[1] overall should be 1 + padding (rather than 8 + padding, which it currently is).

1         2  3  4
a         b  c  d
asdf1234  f  g  h
 => nil

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.