remedy 0.3.1 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2efe0ed0180c60202b73b0cf9f0fce46b51bcfeefe2a83171f4915c9d2b022ad
4
- data.tar.gz: 2b11a6544dec2796c6bdf5ce96691be0c7b232f132174d0b79496098252fe5ab
3
+ metadata.gz: 3a8fe8ed0c57993d0c71fa5d584dce0343e6548d4b42ce70431333fb62d9490d
4
+ data.tar.gz: 0eab58e635c11d57b167d842ce6411d4970ac9d4a4adb4660b057a4ae2d7b217
5
5
  SHA512:
6
- metadata.gz: c76c67debc47dd95b9b614a6681923cb5e47f53c4135335c39170243bcb9a007630af5bc364894f33489cde79c5692e9a28d97ed0f5caf0bfbe83e229ad394eb
7
- data.tar.gz: a001aa18bd36640ebe267c8d6ae4bf68e7e73d60df0017e31875b222ff30b87169c4c36d06130c27096def9e4ccfa26c50ad350ea1d2cf2adbb42228af5dcf8d
6
+ metadata.gz: 4206bd86137641bea396f02d9935488e7b099c65515d41312e372f9ad8dc0c80d8352190049a92907f2c6db78e0a1a438fa7743a418ee5cdcfe59612e2cafcb2
7
+ data.tar.gz: 9f4d5f519809aa4d2c720358f82c888657235781d4713ba705a35331e3ad6c24396b0031b05cae74d5cfef0c1996e8a56180766b363fd473aa42fcd90cc6cc7f
@@ -10,7 +10,7 @@ jobs:
10
10
  strategy:
11
11
  fail-fast: false
12
12
  matrix:
13
- ruby: ["2.3", "2.4", "2.5", "2.6", "2.7", "3.0", "3.1", "3.2", ruby-head, jruby-9.2, jruby-9.3, jruby-head]
13
+ ruby: ["2.5", "2.6", "2.7", "3.0", "3.1", "3.2", "3.3", "3.4", ruby-head, jruby-10.0, jruby-head]
14
14
 
15
15
  steps:
16
16
  - uses: actions/checkout@v4
data/README.markdown CHANGED
@@ -110,7 +110,7 @@ The most interesting function in my opinion is the callback that gets triggered
110
110
  Remedy in the Wild
111
111
  ------------------
112
112
 
113
- Remedy was originally written for my own console-based game which was sort of like Dwarf Fortress. Most of the project files were lost, but since Remedy was extracted from it and open-sourced it has lived on.
113
+ Remedy was originally written for my own console-based game. Remedy was extracted from it and open-sourced and it has lived on.
114
114
 
115
115
  Here are some projects that use Remedy:
116
116
 
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "remedy", path: "../.."
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "remedy", path: "../.."
@@ -11,11 +11,6 @@ class Menu
11
11
 
12
12
  # will do basic setup and then loop over user input
13
13
  def listen
14
- # get the screen in a reliable state and clear it
15
- ANSI.screen.safe_reset!
16
- ANSI.cursor.home!
17
- ANSI.command.clear_screen!
18
-
19
14
  # if the user resizes the screen we redraw it to fit the new dimensions
20
15
  Console.set_console_resized_hook! do |size|
21
16
  draw
@@ -24,10 +19,10 @@ class Menu
24
19
  # create an interaction object to handle user input
25
20
  interaction = Interaction.new
26
21
 
27
- # call draw here because interaction blocks until it gets input
22
+ # call draw here because the interaction loop blocks until it gets input
28
23
  draw
29
24
 
30
- # loop over user input (individual keypresses)
25
+ # loop over individual keypresses or ANSI codes from the terminal
31
26
  interaction.loop do |key|
32
27
  @last_key = key
33
28
  if key == "q" then
@@ -39,7 +34,7 @@ class Menu
39
34
 
40
35
  # this tells the Viewport to draw to the screen
41
36
  def draw
42
- @viewport.draw content, Size([0,0]), header, footer
37
+ @viewport.draw content, Size.zero, header, footer
43
38
  end
44
39
 
45
40
  # this is the body of our menu, it will be squished if the terminal is too small
@@ -23,6 +23,14 @@ module Remedy
23
23
  @output ||= $stdout
24
24
  end
25
25
 
26
+ def input= new_input
27
+ @input = new_input
28
+ end
29
+
30
+ def output= new_output
31
+ @output = new_output
32
+ end
33
+
26
34
  def raw
27
35
  raw!
28
36
  result = yield
@@ -52,21 +60,27 @@ module Remedy
52
60
  alias_method :height, :rows
53
61
 
54
62
  def size
63
+ return @size_override if @size_override
64
+
55
65
  str = [0, 0, 0, 0].pack('SSSS')
56
- if input.ioctl(TIOCGWINSZ, str) >= 0 then
66
+ if input.respond_to?(:ioctl) && input.ioctl(TIOCGWINSZ, str) >= 0 then
57
67
  Size.new str.unpack('SSSS').first 2
58
68
  else
59
69
  raise UnknownConsoleSize, "Unable to get console size"
60
70
  end
61
71
  end
62
72
 
73
+ def size_override= new_size
74
+ @size_override = new_size
75
+ end
76
+
63
77
  def interactive?
64
78
  input.isatty
65
79
  end
66
80
 
67
81
  def set_console_resized_hook!
68
82
  Console::Resize.set_console_resized_hook! do |*args|
69
- yield *args
83
+ yield(*args)
70
84
  end
71
85
  end
72
86
 
@@ -37,6 +37,7 @@ module Remedy; module Console; module Resize
37
37
  end
38
38
  end
39
39
 
40
+ ensure
40
41
  resized!
41
42
  end
42
43
  end
@@ -68,7 +68,7 @@ module Remedy
68
68
  print " -- #{message}" if message
69
69
 
70
70
  ANSI.cursor.hide!
71
- key = Keyboard.get
71
+ Keyboard.get
72
72
  end
73
73
  end
74
74
  end
@@ -16,6 +16,7 @@ module Remedy
16
16
  reset_width!
17
17
  line = "#{line}" # opportunistically convert any object into a string
18
18
  @lines += clean line unless line.nil? || line.empty?
19
+ self
19
20
  end
20
21
 
21
22
  def first
@@ -26,16 +27,17 @@ module Remedy
26
27
  lines.last
27
28
  end
28
29
 
29
- def length
30
+ def height
30
31
  lines.length
31
32
  end
33
+ alias_method :length, :height
32
34
 
33
35
  def width
34
- @width ||= lines.max{|line| line.length }.length
36
+ lines.map{|line| line.length }.max || 0
35
37
  end
36
38
 
37
39
  def size
38
- Size.new length, width
40
+ Size.new height, width
39
41
  end
40
42
 
41
43
  def to_a
data/lib/remedy/size.rb CHANGED
@@ -11,6 +11,10 @@ module Remedy
11
11
  end
12
12
  attr_accessor :dimensions
13
13
 
14
+ def self.zero
15
+ self.new([0,0])
16
+ end
17
+
14
18
  def - other_size
15
19
  if other_size.respond_to? :length then
16
20
  self.class.new subtract(other_size)
@@ -41,11 +45,13 @@ module Remedy
41
45
  def rows
42
46
  dimensions[0]
43
47
  end
48
+ alias_method :height, :rows
44
49
 
45
50
  def cols
46
51
  dimensions[1]
47
52
  end
48
- alias :columns :cols
53
+ alias_method :columns, :cols
54
+ alias_method :width, :cols
49
55
 
50
56
  def [] index
51
57
  dimensions[index]
@@ -1,3 +1,3 @@
1
1
  module Remedy
2
- VERSION = '0.3.1'
2
+ VERSION = '0.5.0'
3
3
  end
@@ -5,14 +5,10 @@ require 'remedy/ansi'
5
5
 
6
6
  module Remedy
7
7
  class Viewport
8
- def draw content, center = Size.new(0,0), header = [], footer = []
9
- range = range_find content, center, content_size(header,footer)
8
+ def draw content, scroll = Size.zero, header = Partial.new, footer = Partial.new
9
+ range = range_find content, scroll, available_space(header,footer)
10
10
 
11
- if content.size.fits_into? range then
12
- viewable_content = content
13
- else
14
- viewable_content = content.excerpt *range
15
- end
11
+ viewable_content = content.excerpt(*range)
16
12
 
17
13
  view = View.new viewable_content, header, footer
18
14
 
@@ -20,40 +16,49 @@ module Remedy
20
16
  Console.output << view
21
17
  end
22
18
 
23
- def range_find partial, center, heightwidth
24
- row_size, col_size = heightwidth
25
- row_limit, col_limit = partial.size
19
+ def range_find partial, scroll, available_heightwidth
20
+ avail_height, avail_width = available_heightwidth
21
+ partial_height, partial_width = partial.size
22
+
23
+ center_row, center_col = scroll
26
24
 
27
- center_row, center_col = center
25
+ row_range = get_range center_row, partial_height, avail_height
26
+ col_range = get_range center_col, partial_width, avail_width
28
27
 
29
- row_range = center_range center_row, row_size, row_limit
30
- col_range = center_range center_col, col_size, col_limit
31
28
  [row_range, col_range]
32
29
  end
33
30
 
34
- def content_size header, footer
35
- trim = Size [header.length + footer.length, 0]
31
+ # This determines the maximum amount of room left available for Content
32
+ # after taking into consideration the height of the Header and Footer
33
+ def available_space header, footer
34
+ trim = Size [header.height + footer.height, 0]
36
35
  size - trim
37
36
  end
38
37
 
39
38
  def size
40
- Size Console.size
39
+ Console.size
41
40
  end
42
41
 
43
- def center_range center, width, limit
44
- range_start = center - (width / 2)
42
+ def get_range offset, actual, available
43
+ # if the actual content can fit into the available space, then we're done
44
+ return (0...actual) if actual <= available
45
45
 
46
- if range_start + width > limit then
47
- range_start = limit - width
48
- end
46
+ # otherwise start looking at the scrolling offset, if any
49
47
 
50
- if range_start < 0 then
48
+ # clamp the offset within the possible range of the actual content
49
+ if offset < 0 then
51
50
  range_start = 0
51
+ elsif offset > actual then
52
+ range_start = actual
53
+ else
54
+ range_start = offset
52
55
  end
53
56
 
54
- range_end = range_start + width
57
+ # determine the subset of content that can be displayed
58
+ range_end = range_start + (available - offset)
55
59
 
56
60
  (range_start...range_end)
57
61
  end
62
+
58
63
  end
59
64
  end
data/remedy.gemspec CHANGED
@@ -18,5 +18,8 @@ Gem::Specification.new do |gem|
18
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
19
  gem.require_paths = ["lib"]
20
20
 
21
+ gem.required_ruby_version = '>=2.5'
22
+
21
23
  gem.add_development_dependency 'rspec'
24
+ gem.add_development_dependency 'rake'
22
25
  end
@@ -1,13 +1,34 @@
1
- require_relative 'spec_helper'
2
- require 'remedy/viewport'
1
+ require_relative "spec_helper"
2
+ require "remedy/viewport"
3
3
 
4
4
  describe Remedy::Viewport do
5
+ let(:console){ ::Remedy::Console }
6
+ let(:size_override){ Size 20, 40 }
7
+ let(:stringio){ StringIO.new }
8
+
9
+ before(:each) do
10
+ console.input = stringio
11
+ console.output = stringio
12
+ console.size_override = size_override
13
+ end
14
+
15
+ after(:each) do
16
+ console.input = $stdin
17
+ console.output = $stdout
18
+ console.size_override = nil
19
+ end
20
+
5
21
  it 'should be able to execute the example code from the readme' do
22
+ expected = "\\e[H\\e[JQ: What's the difference between a duck?\\e[1B\\e[0GA: Purple, because ice cream has no bone\\e[1B\\e[0G"
23
+
6
24
  joke = ::Remedy::Partial.new
7
25
  joke << "Q: What's the difference between a duck?"
8
26
  joke << "A: Purple, because ice cream has no bones!"
9
27
 
10
28
  screen = ::Remedy::Viewport.new
11
- screen.draw joke unless ENV['CI']
29
+ screen.draw joke
30
+
31
+ actual = stringio.string.inspect[1..-2]
32
+ expect(actual).to eq expected
12
33
  end
13
34
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: remedy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anthony M. Cook
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-04 00:00:00.000000000 Z
11
+ date: 2025-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  description: Pure Ruby console interaction library in the vein of Curses with MVC-style
28
42
  seperation of concerns.
29
43
  email:
@@ -37,12 +51,13 @@ files:
37
51
  - ".gitignore"
38
52
  - ".ruby-gemset"
39
53
  - ".ruby-version"
40
- - ".travis.yml"
41
54
  - Gemfile
42
55
  - LICENSE.txt
43
56
  - README.markdown
44
57
  - Rakefile
58
+ - examples/from_readme/Gemfile
45
59
  - examples/from_readme/readme.rb
60
+ - examples/menu/Gemfile
46
61
  - examples/menu/menu.rb
47
62
  - lib/remedy.rb
48
63
  - lib/remedy/ansi.rb
@@ -75,7 +90,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
75
90
  requirements:
76
91
  - - ">="
77
92
  - !ruby/object:Gem::Version
78
- version: '0'
93
+ version: '2.5'
79
94
  required_rubygems_version: !ruby/object:Gem::Requirement
80
95
  requirements:
81
96
  - - ">="
data/.travis.yml DELETED
@@ -1,16 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.3.1
4
- - 2.2.5
5
- - 2.1.9
6
- - ruby-head
7
-
8
- before_install:
9
- - gem update bundler
10
- script: bundle exec rspec
11
-
12
- matrix:
13
- allow_failures:
14
- - rvm: ruby-head
15
-
16
- sudo: false