remedy 0.0.3.pre

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in remedy.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Anthony Cook
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,33 @@
1
+ Remedy
2
+ ======
3
+
4
+ Remedy is a console interaction framework along the lines of Curses written in pure Ruby with an Object-Oriented approach and baked-in support for bulding MVC applications.
5
+
6
+ Installation
7
+ ------------
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'remedy'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install remedy
20
+
21
+ Usage
22
+ -----
23
+
24
+ TODO: Write usage instructions here
25
+
26
+ Contributing
27
+ ------------
28
+
29
+ 1. Fork it
30
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
31
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
32
+ 4. Push to the branch (`git push origin my-new-feature`)
33
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/lib/remedy.rb ADDED
@@ -0,0 +1,9 @@
1
+ %w{
2
+ version ansi characters console resized_console content header footer
3
+ interaction key keyboard partial view viewport
4
+ }.each do |lib|
5
+ require "remedy/#{lib}"
6
+ end
7
+
8
+ module Remedy
9
+ end
@@ -0,0 +1,207 @@
1
+ require 'remedy/console'
2
+
3
+ module Remedy
4
+ module ANSI
5
+ module_function
6
+
7
+ def push *sequences
8
+ Console.output << sequences.join('')
9
+ end
10
+
11
+ def pushesc *sequences
12
+ push sequences.map{|sequence| esc sequence }
13
+ end
14
+
15
+ def pushe *sequences
16
+ push sequences.map{|sequence| e sequence }
17
+ end
18
+
19
+ def esc sequence = nil
20
+ "\e[#{sequence}"
21
+ end
22
+
23
+ def e sequence = nil
24
+ "\e#{sequence}"
25
+ end
26
+
27
+ def cursor
28
+ Cursor
29
+ end
30
+
31
+ def screen
32
+ Screen
33
+ end
34
+
35
+ def command
36
+ Command
37
+ end
38
+
39
+ def color
40
+ Color
41
+ end
42
+
43
+ module Command
44
+ extend ANSI
45
+
46
+ module_function
47
+
48
+ def code
49
+ {
50
+ clear_line: 'K',
51
+
52
+ clear_down: 'J',
53
+ clear_up: '1J',
54
+ clear_screen: '2J'
55
+ }
56
+ end
57
+
58
+ def clear_line!
59
+ pushesc code[:clear_line]
60
+ end
61
+
62
+ def clear_up!
63
+ pushesc code[:clear_up]
64
+ end
65
+
66
+ def clear_down!
67
+ pushesc code[:clear_down]
68
+ end
69
+
70
+ def clear_screen!
71
+ pushesc code[:clear_screen]
72
+ end
73
+ end
74
+
75
+ module Cursor
76
+ extend ANSI
77
+
78
+ module_function
79
+
80
+ def code
81
+ {
82
+ # Movement
83
+ home: 'H',
84
+ up: '%{lines}A',
85
+ down: '%{lines}B',
86
+ to_column: '%{column}G',
87
+
88
+ # May not work on all terminals.
89
+ next_line: '%{lines}E',
90
+ prev_line: '%{lines}F',
91
+
92
+ # Visiblity
93
+ show: '?25h',
94
+ hide: '?25l'
95
+ }
96
+ end
97
+
98
+ def to_column column
99
+ esc code[:to_column] % {column: column}
100
+ end
101
+
102
+ def down lines = 1
103
+ esc code[:down] % {lines: lines}
104
+ end
105
+
106
+ def up lines = 1
107
+ esc code[:up] % {lines: lines}
108
+ end
109
+
110
+ def next_line lines = 1
111
+ #esc code[:next_line] % {lines: lines}
112
+ down(lines) + to_column(0)
113
+ end
114
+
115
+ def prev_line lines = 1
116
+ #esc code[:prev_line] % {lines: lines}
117
+ up(lines) + to_column(0)
118
+ end
119
+
120
+
121
+ def home!
122
+ pushesc code[:home]
123
+ end
124
+
125
+ def hide!
126
+ pushesc code[:hide]
127
+ end
128
+
129
+ def show!
130
+ pushesc code[:show]
131
+ end
132
+
133
+ def next_line! lines = 1
134
+ push next_line(lines)
135
+ end
136
+
137
+ def prev_line! lines = 1
138
+ push prev_line(lines)
139
+ end
140
+
141
+ def beginning_of_line!
142
+ to_column! 0
143
+ end
144
+
145
+ end
146
+
147
+ module Screen
148
+ extend ANSI
149
+
150
+ module_function
151
+
152
+ def code
153
+ {
154
+ up: 'M',
155
+ down: 'D'
156
+ }
157
+ end
158
+
159
+ def reset!
160
+ ANSI.color.reset!
161
+ ANSI.cursor.home!
162
+ clear!
163
+ end
164
+
165
+ def safe_reset!
166
+ ANSI.cursor.home!
167
+ ANSI.command.clear_down!
168
+ end
169
+
170
+ def clear!
171
+ ANSI.command.clear_screen!
172
+ end
173
+
174
+ def up! count = 1
175
+ count.times { pushe code[:up] }
176
+ end
177
+
178
+ def down! count = 1
179
+ count.times { pushe code[:down] }
180
+ end
181
+ end
182
+
183
+ module Color
184
+ extend ANSI
185
+
186
+ module_function
187
+
188
+ def code
189
+ {
190
+ reset: '0'
191
+ }
192
+ end
193
+
194
+ def pushc *sequences
195
+ push sequences.map{|sequence| c sequence }
196
+ end
197
+
198
+ def c sequence
199
+ "#{esc sequence}m"
200
+ end
201
+
202
+ def reset!
203
+ pushc code[:reset]
204
+ end
205
+ end
206
+ end
207
+ end
@@ -0,0 +1,155 @@
1
+ module Remedy
2
+ module Characters
3
+ module_function
4
+
5
+ def [] sequence_to_match
6
+ all[sequence_to_match]
7
+ end
8
+
9
+ def all
10
+ @all ||= printable.merge(nonprintable)
11
+ end
12
+
13
+ def printable
14
+ @printable ||= whitespace.merge(
15
+ alphabetical.merge(
16
+ numeric.merge(
17
+ punctuation)))
18
+ end
19
+
20
+ def whitespace
21
+ {
22
+ ' ' => :space,
23
+ "\t" => :tab,
24
+ "\r" => :carriage_return,
25
+ "\n" => :line_feed
26
+ }
27
+ end
28
+
29
+ def alphabetical
30
+ @alphabetics ||= get_alphabetics
31
+ end
32
+
33
+ def numeric
34
+ {
35
+ '0' => :zero,
36
+ '1' => :one,
37
+ '2' => :two,
38
+ '3' => :three,
39
+ '4' => :four,
40
+ '5' => :five,
41
+ '6' => :six,
42
+ '7' => :seven,
43
+ '8' => :eight,
44
+ '9' => :nine
45
+ }
46
+ end
47
+
48
+ def punctuation
49
+ {
50
+ '.' => :period,
51
+ ',' => :comma,
52
+ ':' => :colon,
53
+ ';' => :semicolon,
54
+
55
+ '"' => :double_quote,
56
+ "'" => :single_quote,
57
+ '`' => :back_quote,
58
+
59
+ '[' => :left_bracket,
60
+ ']' => :right_bracked,
61
+ '(' => :left_paren,
62
+ ')' => :right_paren,
63
+
64
+ '^' => :caret,
65
+ '_' => :underscore,
66
+ '-' => :dash,
67
+ '~' => :tilde,
68
+
69
+ '!' => :bang,
70
+ '?' => :query,
71
+
72
+ '|' => :solid_pipe,
73
+ "\u00A6" => :broken_pipe,
74
+
75
+ '/' => :forward_slash,
76
+ "\\" => :back_slash
77
+ }
78
+ end
79
+
80
+ def nonprintable
81
+ @nonprintable ||= special.merge(directional).merge(escape).merge(control)
82
+ end
83
+
84
+ def special
85
+ {
86
+ "\177" => :backspace
87
+ }
88
+ end
89
+
90
+ def directional
91
+ {
92
+ "\e[A" => :up,
93
+ "\e[B" => :down,
94
+ "\e[D" => :left,
95
+ "\e[C" => :right
96
+ }
97
+ end
98
+
99
+ def escape
100
+ {
101
+ "\e" => :escape,
102
+
103
+ "\e[3~" => :delete
104
+ }
105
+ end
106
+
107
+ def control
108
+ {
109
+ "\u0003" => :control_c,
110
+ "\u0004" => :control_d,
111
+ "\u0012" => :control_r
112
+ }
113
+ end
114
+
115
+ def gremlins
116
+ {
117
+ space: "\u2420",
118
+ tab: "\u21B9",
119
+ carriage_return: "\u23CE",
120
+ line_feed: "\u240A",
121
+
122
+ control_c: "\u2404",
123
+ control_d: "\u2403",
124
+ control_r: "\u2412",
125
+
126
+ escape: "\u238B",
127
+
128
+ backspace: "\u2408",
129
+ delete: "\u232B",
130
+
131
+ up: "\u2191",
132
+ down: "\u2193",
133
+ left: "\u2190",
134
+ right: "\u2192"
135
+ }
136
+ end
137
+
138
+ def alternate_names
139
+ {
140
+ control_c: :end_of_transmission,
141
+ control_d: :end_of_text,
142
+
143
+ control_r: :device_control_two
144
+ }
145
+ end
146
+
147
+ def get_alphabetics
148
+ letters = ('a'..'z').to_a + ('A'..'Z').to_a
149
+ letters.inject(Hash.new) do |alphas, letter|
150
+ alphas[letter] = letter.to_sym
151
+ alphas
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,61 @@
1
+ require 'remedy/console_resized'
2
+
3
+ module Remedy
4
+ module Console
5
+ require 'io/console'
6
+
7
+ TIOCGWINSZ = 0x40087468
8
+
9
+ module_function
10
+
11
+ def input
12
+ STDIN
13
+ end
14
+
15
+ def output
16
+ STDOUT
17
+ end
18
+
19
+ def raw
20
+ raw!
21
+ result = yield
22
+ ensure
23
+ cooked!
24
+
25
+ return result
26
+ end
27
+
28
+ def raw!
29
+ input.echo = false
30
+ input.raw!
31
+ end
32
+
33
+ def cooked!
34
+ input.echo = true
35
+ input.cooked!
36
+ rescue NoMethodError
37
+ %x{stty -raw echo 2> /dev/null}
38
+ end
39
+
40
+ def size
41
+ str = [0, 0, 0, 0].pack('SSSS')
42
+ if input.ioctl(TIOCGWINSZ, str) >= 0 then
43
+ str.unpack('SSSS').first 2
44
+ else
45
+ raise UnknownConsoleSize, "Unable to get console size"
46
+ end
47
+ end
48
+
49
+ def interactive?
50
+ input.isatty
51
+ end
52
+
53
+ def set_console_resized_hook!
54
+ ConsoleResized.set_console_resized_hook! do
55
+ yield
56
+ end
57
+ end
58
+
59
+ class UnknownConsoleSize < IOError; end
60
+ end
61
+ end
@@ -0,0 +1,46 @@
1
+ module Remedy
2
+ module ConsoleResized
3
+ module_function
4
+
5
+ def resizing?
6
+ @resize_count > 0
7
+ end
8
+
9
+ def resizing!
10
+ @resize_count = @resize_count < 1 ? 1 : @resize_count + 1
11
+ end
12
+
13
+ def resized?
14
+ @resize_count <= 1
15
+ end
16
+
17
+ def resized!
18
+ @resize_count = @resize_count < 0 ? 0 : @resize_count - 1
19
+ end
20
+
21
+ def resizer?
22
+ @resize_count == 1
23
+ end
24
+
25
+ def set_console_resized_hook!
26
+ @resize_count = 0
27
+
28
+ command = lambda { |x|
29
+ resizing!
30
+ sleep 0.25
31
+
32
+ if resized? then
33
+ yield
34
+ end
35
+
36
+ resized!
37
+ }
38
+
39
+ Signal.trap 'SIGWINCH', command
40
+ end
41
+
42
+ def default_console_resized_hook!
43
+ Signal.trap 'SIGWINCH', 'DEFAULT'
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,4 @@
1
+ require 'partial'
2
+
3
+ class Content < Partial
4
+ end
@@ -0,0 +1,7 @@
1
+ require 'remedy/partial'
2
+
3
+ module Remedy
4
+ class Footer < Partial
5
+ end
6
+ end
7
+
@@ -0,0 +1,7 @@
1
+ require 'remedy/partial'
2
+
3
+ module Remedy
4
+ class Header < Partial
5
+ end
6
+ end
7
+
@@ -0,0 +1,65 @@
1
+ require 'remedy/keyboard'
2
+ require 'remedy/ansi'
3
+
4
+ class Interaction
5
+ def initialize message = nil
6
+ @message = message
7
+ end
8
+
9
+ attr_accessor :message
10
+
11
+ def confirm message = 'Confirm?'
12
+ ANSI.cursor.home!
13
+ ANSI.command.clear_line!
14
+
15
+ print message, ' y/n '
16
+ if Keyboard.get === :y then
17
+ yield if block_given?
18
+ true
19
+ else
20
+ false
21
+ end
22
+ end
23
+
24
+ def quit!
25
+ confirm 'Are you sure you want to quit? You will lose everything. :(' do
26
+ ANSI.cursor.home!
27
+ ANSI.command.clear_down!
28
+ ANSI.cursor.show!
29
+
30
+ puts " -- Bye!"
31
+ exit
32
+ end
33
+ end
34
+
35
+ def debug!
36
+ require 'pry'
37
+ binding.pry
38
+ end
39
+
40
+ def display key
41
+ ANSI.command.clear_line!
42
+ print " -- You pressed: #{key.inspect}"
43
+ end
44
+
45
+ def loop
46
+ Keyboard.raise_on_control_c!
47
+
48
+ super do
49
+ print " -- #{message}" if message
50
+
51
+ ANSI.cursor.hide!
52
+ key = Keyboard.get
53
+
54
+ if key == ?\C-q then
55
+ display key
56
+ quit!
57
+ elsif key == ?\C-d and defined? Pry then
58
+ display key
59
+ debug!
60
+ end
61
+
62
+ yield key
63
+ end
64
+ end
65
+ end
data/lib/remedy/key.rb ADDED
@@ -0,0 +1,117 @@
1
+ require 'remedy/characters'
2
+
3
+ module Remedy
4
+ class Key
5
+
6
+ def initialize character_sequence
7
+ @character_sequence = character_sequence
8
+ end
9
+
10
+ def seq
11
+ @character_sequence
12
+ end
13
+
14
+ def raw
15
+ seq
16
+ end
17
+
18
+ def name
19
+ @name ||= Characters[seq] || :unknown
20
+ end
21
+
22
+ def glyph
23
+ @glyph ||= get_glyph
24
+ end
25
+
26
+ def printable?
27
+ @printable ||= !!Characters.printable[seq]
28
+ end
29
+
30
+ def nonprintable?
31
+ @nonprintable ||= !!Characters.nonprintable[seq]
32
+ end
33
+
34
+ def control?
35
+ @control ||= !!Characters.control[seq]
36
+ end
37
+
38
+ def punctuation?
39
+ @control ||= !!Characters.punctuation[seq]
40
+ end
41
+
42
+ def gremlin?
43
+ @gremlin ||= !!Characters.gremlins[name]
44
+ end
45
+
46
+ def control_c?
47
+ @control_c ||= seq == Characters.control.key(:control_c)
48
+ end
49
+
50
+ def recognized?
51
+ @recognized ||= name != :unknown
52
+ end
53
+
54
+ def single?
55
+ @single ||= raw.length == 1
56
+ end
57
+
58
+ def sequence?
59
+ @sequence ||= raw.legnth > 1
60
+ end
61
+
62
+ def to_s
63
+ @to_s ||= name.to_s
64
+ end
65
+
66
+ def value
67
+ raw_value = raw.bytes.to_a.join(' ')
68
+ single? ? raw_value : "(#{raw_value})"
69
+ end
70
+
71
+ def inspect
72
+ "<#{self.class} #{name.inspect} value:#{value} glyph:#{glyph}>"
73
+ end
74
+
75
+ def == key
76
+ if key.respond_to? :raw then
77
+ key.raw == raw
78
+ else
79
+ "#{raw}" == "#{key}"
80
+ end
81
+ end
82
+
83
+ def eql? key
84
+ if key.is_a? self.class then
85
+ self == key
86
+ end
87
+ end
88
+
89
+ def === object
90
+ "#{object}" =~ /#{to_s}/i
91
+ end
92
+
93
+ def hash
94
+ raw.hash
95
+ end
96
+
97
+ protected
98
+
99
+ def get_glyph
100
+ if punctuation? then
101
+ seq
102
+ elsif gremlin? then
103
+ Characters.gremlins[name]
104
+ else
105
+ recognized? ? name : ''
106
+ end
107
+ end
108
+ end
109
+
110
+ def Key object
111
+ if object.is_a? Key then
112
+ object
113
+ else
114
+ Key.new object
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,66 @@
1
+ require 'remedy/console'
2
+ require 'remedy/key'
3
+
4
+ module Keyboard
5
+ module_function
6
+
7
+ def get
8
+ parse raw_get
9
+ end
10
+
11
+ def raw_get
12
+ Console.raw do
13
+ input = STDIN.getc.chr
14
+
15
+ if input == "\e" then
16
+ input << STDIN.read_nonblock(3) rescue nil
17
+ input << STDIN.read_nonblock(2) rescue nil
18
+ end
19
+
20
+ input
21
+ end
22
+ end
23
+
24
+ def parse sequence
25
+ key = Key.new sequence
26
+ $log.debug "Key read", key
27
+
28
+ if raise_on_control_c? && key.control_c? then
29
+ raise ControlC, "User pressed Control-C"
30
+ elsif key.recognized? then
31
+ key
32
+ elsif raise_on_unrecognized_key? then
33
+ raise UnrecognizedInput, %Q{Unknown key or byte sequence: "#{sequence}" : #{key.inspect}}
34
+ else
35
+ key
36
+ end
37
+ end
38
+
39
+ def raise_on_unrecognized_key?
40
+ @raise_on_unrecognized_key
41
+ end
42
+
43
+ def raise_on_unrecognized_key!
44
+ @raise_on_unrecognized_key = true
45
+ end
46
+
47
+ def dont_raise_on_unrecognized_key!
48
+ @raise_on_unrecognized_key = false
49
+ end
50
+
51
+ def raise_on_control_c?
52
+ @raise_on_control_c
53
+ end
54
+
55
+ def raise_on_control_c!
56
+ @raise_on_control_c = true
57
+ end
58
+
59
+ def dont_raise_on_control_c!
60
+ @raise_on_control_c = false
61
+ end
62
+
63
+ class ControlC < Interrupt; end
64
+ class UnrecognizedInput < IOError; end
65
+ end
66
+
@@ -0,0 +1,70 @@
1
+ module Remedy
2
+ class Partial
3
+ def initialize collection = Array.new
4
+ @lines = Array.new
5
+ self + collection
6
+ end
7
+ attr_accessor :lines
8
+
9
+ def + new_lines
10
+ new_lines.each do |line|
11
+ self << line
12
+ end
13
+ end
14
+
15
+ def << line
16
+ reset_width!
17
+ @lines += clean line unless line.nil? || line.empty?
18
+ end
19
+
20
+ def first
21
+ lines.first
22
+ end
23
+
24
+ def last
25
+ lines.last
26
+ end
27
+
28
+ def length
29
+ lines.length
30
+ end
31
+
32
+ def width
33
+ @width ||= lines.max{|line| line.length }
34
+ end
35
+
36
+ def size
37
+ Size.new length, width
38
+ end
39
+
40
+ def to_a
41
+ lines
42
+ end
43
+
44
+ def to_s
45
+ lines.join '\n'
46
+ end
47
+
48
+ def join seperator
49
+ lines.join seperator
50
+ end
51
+
52
+ def excerpt lines_range, width_range
53
+ self.class.new lines[lines_range].map { |line| line[width_range] }
54
+ end
55
+
56
+ protected
57
+
58
+ def reset_width!
59
+ @width = nil
60
+ end
61
+
62
+ def clean line
63
+ Array split(line)
64
+ end
65
+
66
+ def split line
67
+ line.split /\r\n|\n\r|\n|\r/
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,3 @@
1
+ module Remedy
2
+ VERSION = "0.0.3.pre"
3
+ end
@@ -0,0 +1,43 @@
1
+ module Remedy
2
+ class View
3
+ def initialize body, header = [], footer = []
4
+ @header, @body, @footer = header, body, footer
5
+ end
6
+ attr_accessor :body, :header, :footer, :length
7
+
8
+ def to_s force_recompile = false
9
+ unless @view.nil? || force_recompile then
10
+ @view
11
+ else
12
+ reset_length!
13
+ @view = compile!
14
+ end
15
+ end
16
+
17
+ protected
18
+
19
+ def compile!
20
+ compiled_view = String.new
21
+ reset_length!
22
+
23
+ merged.each do |line|
24
+ compiled_view << row(line)
25
+ end
26
+
27
+ compiled_view
28
+ end
29
+
30
+ def merged
31
+ @header.to_a + @body.to_a + @footer.to_a
32
+ end
33
+
34
+ def row line
35
+ @length += 1
36
+ "#{line}#{ANSI.cursor.next_line}"
37
+ end
38
+
39
+ def reset_length!
40
+ @length = 0
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,58 @@
1
+ require 'remedy/view'
2
+ require 'remedy/size'
3
+ require 'remedy/content'
4
+
5
+ module Remedy
6
+ class Viewport
7
+ def draw content, center = Size.new(0,0), header = [], footer = []
8
+ range = range_find content, center, content_size(header,footer)
9
+
10
+ if content.size.fits_into? range then
11
+ viewable_content = content
12
+ else
13
+ viewable_content = content.excerpt *range
14
+ end
15
+
16
+ view = View.new viewable_content, header, footer
17
+
18
+ ANSI.screen.safe_reset!
19
+ Console.output << view
20
+ end
21
+
22
+ def range_find map, center, heightwidth
23
+ row_size, col_size = heightwidth
24
+ row_limit, col_limit = map.size
25
+
26
+ center_row, center_col = center.coords
27
+
28
+ row_range = center_range center_row, row_size, row_limit
29
+ col_range = center_range center_col, col_size, col_limit
30
+ [row_range, col_range]
31
+ end
32
+
33
+ def content_size header, footer
34
+ trim = Size [header.length + footer.length, 0]
35
+ size - trim
36
+ end
37
+
38
+ def size
39
+ Size Console.size
40
+ end
41
+
42
+ def center_range center, width, limit
43
+ range_start = center - (width / 2)
44
+
45
+ if range_start + width > limit then
46
+ range_start = limit - width
47
+ end
48
+
49
+ if range_start < 0 then
50
+ range_start = 0
51
+ end
52
+
53
+ range_end = range_start + width
54
+
55
+ (range_start...range_end)
56
+ end
57
+ end
58
+ end
data/remedy.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'remedy/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "remedy"
8
+ gem.version = Remedy::VERSION
9
+ gem.authors = ["Anthony M. Cook"]
10
+ gem.email = ["anthonymichaelcook@gmail.com"]
11
+ gem.description = %q{Pure Ruby console interaction library in the vein of Curses with baked-in MVC support.}
12
+ gem.summary = %q{MVC Console Interaction Library}
13
+ gem.homepage = "http://github.com/acook/remedy"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: remedy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3.pre
5
+ prerelease: 6
6
+ platform: ruby
7
+ authors:
8
+ - Anthony M. Cook
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-31 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Pure Ruby console interaction library in the vein of Curses with baked-in
15
+ MVC support.
16
+ email:
17
+ - anthonymichaelcook@gmail.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - Gemfile
24
+ - LICENSE.txt
25
+ - README.markdown
26
+ - Rakefile
27
+ - lib/remedy.rb
28
+ - lib/remedy/ansi.rb
29
+ - lib/remedy/characters.rb
30
+ - lib/remedy/console.rb
31
+ - lib/remedy/console_resized.rb
32
+ - lib/remedy/content.rb
33
+ - lib/remedy/footer.rb
34
+ - lib/remedy/header.rb
35
+ - lib/remedy/interaction.rb
36
+ - lib/remedy/key.rb
37
+ - lib/remedy/keyboard.rb
38
+ - lib/remedy/partial.rb
39
+ - lib/remedy/version.rb
40
+ - lib/remedy/view.rb
41
+ - lib/remedy/viewport.rb
42
+ - remedy.gemspec
43
+ homepage: http://github.com/acook/remedy
44
+ licenses: []
45
+ post_install_message:
46
+ rdoc_options: []
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ none: false
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ! '>'
58
+ - !ruby/object:Gem::Version
59
+ version: 1.3.1
60
+ none: false
61
+ requirements: []
62
+ rubyforge_project:
63
+ rubygems_version: 1.8.24
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: MVC Console Interaction Library
67
+ test_files: []
68
+ has_rdoc: