remedy 0.0.3.pre

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.
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: