ansi-select 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/README.md +41 -0
- data/Rakefile +1 -0
- data/ansi-select.gemspec +23 -0
- data/bin/ansi-select +4 -0
- data/lib/ansi/select.rb +121 -0
- data/lib/ansi/select/version.rb +5 -0
- metadata +85 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: dbdb0d626907ead9edbe0c70ece388639bfd60b2
|
4
|
+
data.tar.gz: f6c5d41601a0ba70f4c5c14ba6b30992968fd6d6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 93fd756748db4238b3fd331c947ae32973596909b04c349d40469688a1dcda566695c5109c1200514c4511f15d56c3e355d44fc3bd528abdd7e6df21a942a573
|
7
|
+
data.tar.gz: beebfe8259573a84716765cbd55d0ac64e394bbb0f8a1aedb3c470972a5665b62070dbe4f3b377f5010fe6fc8756b3fe5d7111a601db708421bf5aa17d66de6b
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ansi-select
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2.2
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+

|
2
|
+
|
3
|
+
## Installation
|
4
|
+
|
5
|
+
$ gem install ansi-select
|
6
|
+
|
7
|
+
|
8
|
+
## Usage
|
9
|
+
|
10
|
+
There are two options:
|
11
|
+
|
12
|
+
* A standalone executable. Lines passed to STDIN will form your options. The result will be printed to STDOUT.
|
13
|
+
|
14
|
+
```bash
|
15
|
+
echo some words to choose from | tr ' ' '\n' | ansi-select
|
16
|
+
cd $(ls -d */ | ansi-select) # Go to a visually selected subdirectory.
|
17
|
+
git checkout $(git branch | ansi-select) # The same, but with git branches.
|
18
|
+
```
|
19
|
+
|
20
|
+
* A Ruby library.
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
require "ansi/select"
|
24
|
+
|
25
|
+
answer = Ansi::Select.new(["some", "words", "to", "choose", "from"]).select
|
26
|
+
print "You chose #{answer}."
|
27
|
+
```
|
28
|
+
|
29
|
+
The Ruby interface has an additional benefit of accepting any objects that respond
|
30
|
+
to `#to_s` and returning one of them instead of a string.
|
31
|
+
|
32
|
+
|
33
|
+
## Keyboard
|
34
|
+
|
35
|
+
You can use up and down keys or `j`/`k` for navigation, and space or return key for choosing an option.
|
36
|
+
If you've changed your mind, you can quit with Ctrl+C or `q`.
|
37
|
+
|
38
|
+
|
39
|
+
## TODO
|
40
|
+
|
41
|
+
* Support multi-select.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/ansi-select.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ansi/select/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ansi-select"
|
8
|
+
spec.version = Ansi::Select::VERSION
|
9
|
+
spec.authors = ["Volodymyr Shatskyi"]
|
10
|
+
spec.email = ["shockone89@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Simple, not full-screen, ncurses-like TUI select}
|
13
|
+
spec.description = %q{This gem allows you to select an array element (where an array is arbitrary input) with a pretty text user interface.}
|
14
|
+
spec.homepage = "https://github.com/shockone/ansi-select"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "bin"
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.9"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
end
|
data/bin/ansi-select
ADDED
data/lib/ansi/select.rb
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require "io/console"
|
4
|
+
|
5
|
+
module Ansi
|
6
|
+
class Select
|
7
|
+
CODES = {
|
8
|
+
standout_mode: `tput rev`,
|
9
|
+
exit_standout_mode: `tput rmso`,
|
10
|
+
cursor_up: `tput cuu1`,
|
11
|
+
cursor_down: `tput cud1`,
|
12
|
+
carriage_return_key: `tput cr`
|
13
|
+
}
|
14
|
+
|
15
|
+
# @param [Array<#to_s>] options
|
16
|
+
def initialize(options)
|
17
|
+
@options = options
|
18
|
+
|
19
|
+
@highlighted_line_index = 0
|
20
|
+
@cursor_line_index = 0
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [#to_s] option
|
24
|
+
def select
|
25
|
+
print_options
|
26
|
+
answer = ask_to_choose
|
27
|
+
go_to_line(@options.size)
|
28
|
+
|
29
|
+
answer
|
30
|
+
ensure
|
31
|
+
tty.close
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# @return [File]
|
37
|
+
def tty
|
38
|
+
@tty ||= File.open('/dev/tty', 'w+')
|
39
|
+
end
|
40
|
+
|
41
|
+
def print_options
|
42
|
+
@options.each.with_index do |_, index|
|
43
|
+
print_line(index, index == @highlighted_line_index)
|
44
|
+
|
45
|
+
unless index == @options.size - 1
|
46
|
+
tty.print $/ # This strange thing is a cross-platform new line.
|
47
|
+
@cursor_line_index += 1
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
go_to_line(0)
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [String]
|
55
|
+
def listen_carefully_to_keyboard
|
56
|
+
tty.noecho do
|
57
|
+
tty.raw do
|
58
|
+
input = tty.getc.chr
|
59
|
+
if input == "\e"
|
60
|
+
input << tty.read_nonblock(3) rescue nil
|
61
|
+
input << tty.read_nonblock(2) rescue nil
|
62
|
+
end
|
63
|
+
|
64
|
+
input
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return [#to_s]
|
70
|
+
def ask_to_choose
|
71
|
+
loop do
|
72
|
+
input = listen_carefully_to_keyboard
|
73
|
+
|
74
|
+
case input
|
75
|
+
when "\u0003", "q"
|
76
|
+
exit(0)
|
77
|
+
when CODES[:carriage_return_key], " "
|
78
|
+
break @options[@highlighted_line_index]
|
79
|
+
when "\e[A", "k", CODES[:cursor_up]
|
80
|
+
highlight_line(@highlighted_line_index - 1) unless @highlighted_line_index == 0
|
81
|
+
when "\e[B", "j", CODES[:cursor_down]
|
82
|
+
highlight_line(@highlighted_line_index + 1) unless @highlighted_line_index == @options.size - 1
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# @param [Fixnum] index
|
88
|
+
# @param [Boolean] highlight
|
89
|
+
def print_line(index, highlight)
|
90
|
+
go_to_line(index)
|
91
|
+
|
92
|
+
if highlight
|
93
|
+
tty.print "#{CODES[:standout_mode]}#{@options[index]}#{CODES[:exit_standout_mode]}"
|
94
|
+
else
|
95
|
+
tty.print @options[index]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# @param [Fixnum] index
|
100
|
+
def highlight_line(index)
|
101
|
+
print_line(@highlighted_line_index, false)
|
102
|
+
print_line(index, true)
|
103
|
+
|
104
|
+
@highlighted_line_index = index
|
105
|
+
end
|
106
|
+
|
107
|
+
# @param [Fixnum] index
|
108
|
+
def go_to_line(index)
|
109
|
+
if index == @cursor_line_index
|
110
|
+
# do nothing
|
111
|
+
elsif index > @cursor_line_index
|
112
|
+
(index - @cursor_line_index).times { tty.print CODES[:cursor_down] }
|
113
|
+
else
|
114
|
+
(@cursor_line_index - index).times { tty.print CODES[:cursor_up] }
|
115
|
+
end
|
116
|
+
|
117
|
+
@cursor_line_index = index
|
118
|
+
tty.print CODES[:carriage_return_key]
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ansi-select
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Volodymyr Shatskyi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-09-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.9'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.9'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
description: This gem allows you to select an array element (where an array is arbitrary
|
42
|
+
input) with a pretty text user interface.
|
43
|
+
email:
|
44
|
+
- shockone89@gmail.com
|
45
|
+
executables:
|
46
|
+
- ansi-select
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- ".gitignore"
|
51
|
+
- ".rspec"
|
52
|
+
- ".ruby-gemset"
|
53
|
+
- ".ruby-version"
|
54
|
+
- ".travis.yml"
|
55
|
+
- Gemfile
|
56
|
+
- README.md
|
57
|
+
- Rakefile
|
58
|
+
- ansi-select.gemspec
|
59
|
+
- bin/ansi-select
|
60
|
+
- lib/ansi/select.rb
|
61
|
+
- lib/ansi/select/version.rb
|
62
|
+
homepage: https://github.com/shockone/ansi-select
|
63
|
+
licenses: []
|
64
|
+
metadata: {}
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 2.4.8
|
82
|
+
signing_key:
|
83
|
+
specification_version: 4
|
84
|
+
summary: Simple, not full-screen, ncurses-like TUI select
|
85
|
+
test_files: []
|