remedy 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b308f7cf135ba7a8f6ab69ef9c56ff7d640a189c9f44056e14f49b987948ec1f
4
- data.tar.gz: 9f1969fea60358a6585974f948f572bdeeeb55afd0f176d6dd220bdd4b29c094
3
+ metadata.gz: af17b629f35cdae5c8a15c47a6e23f5aa51bce006afa7f7e129a8640c9d191b1
4
+ data.tar.gz: 36568e55906c286e97666183f9e6eb704535b6155830bc93acda7c59299a2ab6
5
5
  SHA512:
6
- metadata.gz: 0d664d1b61638b139bd2aef66ed2facd0d25e4dbaa65a39014892bcb3f967895cbf78304a8b4235cce1a5210384e7cadaa6672fa41a2d2e102c22a80c0cd40ef
7
- data.tar.gz: ea8a3d1aeaeb8a0e474bf2a69f6837ab300810dfaf3bd014200e284f6e45058875fa5363e73948228806e35e24957ded1d342d07a8622f089726e94da2e93a3b
6
+ metadata.gz: 447afaf7d518eb6b8ddeb80dc9d7b4cae579a978ec6af952749dafe52b2d95b930ef6e6bbc24378ebab81ec48807102453d07e0f8196b251d62ffd84662f80a9
7
+ data.tar.gz: 7d800899e64c41e9acd31215df9b66fd1dd96f9da52a735e3393c855bf91f8d75f1fc224dc559f9560fedaa89a4c88468cce94b9713bd3bb1ef3e2b428d52e61
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
@@ -0,0 +1,23 @@
1
+ name: CI
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ test:
7
+
8
+ runs-on: ubuntu-latest
9
+
10
+ strategy:
11
+ fail-fast: false
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]
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - name: Set up Ruby
18
+ uses: ruby/setup-ruby@v1
19
+ with:
20
+ bundler-cache: true # 'bundle install' and cache gems
21
+ ruby-version: ${{ matrix.ruby }}
22
+ - name: Run tests
23
+ run: bundle exec rspec
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.6.3
1
+ 3.1.2
data/README.markdown CHANGED
@@ -5,7 +5,7 @@ Remedy is a console interaction framework along the lines of Curses written in p
5
5
 
6
6
  [![Gem Version](https://img.shields.io/gem/v/remedy.svg?style=for-the-badge)](https://rubygems.org/gems/remedy)
7
7
  [![Gem Downloads](https://img.shields.io/gem/dt/remedy.svg?style=for-the-badge)](https://rubygems.org/gems/remedy)
8
- [![Build Status](https://img.shields.io/travis/acook/remedy.svg?style=for-the-badge)](https://travis-ci.org/acook/remedy)
8
+ [![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/acook/remedy/ci.yml?style=for-the-badge)](https://github.com/acook/remedy/actions/workflows/ci.yml)
9
9
  [![Code Climate maintainability](https://img.shields.io/codeclimate/maintainability/acook/remedy?style=for-the-badge)](https://codeclimate.com/github/acook/remedy/maintainability)
10
10
 
11
11
 
@@ -70,20 +70,18 @@ For instance to get a keypress from the terminal and display it:
70
70
  screen.draw joke
71
71
  ```
72
72
 
73
- `Remedy::Partial` has the subclasses `Header`, `Footer`, and `Content`.
74
-
75
- You can use the above classes to divide your Views into 3 separate pieces. Content will be truncated as needed to accommodate the header and footer and the dimensions of the console. You can also specify the cursor/scroll position of the content being drawn, and when specifying headers or footers, you must.
73
+ Content in `Remedy::Partial`s will be truncated as needed to accommodate the header and footer and the dimensions of the console. You can also specify the cursor/scroll position of the content being drawn, and when specifying headers or footers, you must.
76
74
 
77
75
  ```ruby
78
76
  include Remedy
79
- title = Header.new
77
+ title = Partial.new
80
78
  title << "Someone Said These Were Good"
81
79
 
82
80
  jokes = Content.new
83
81
  jokes << %q{1. A woman gets on a bus with her baby. The bus driver says: 'Ugh, that's the ugliest baby I've ever seen!' The woman walks to the rear of the bus and sits down, fuming. She says to a man next to her: 'The driver just insulted me!' The man says: 'You go up there and tell him off. Go on, I'll hold your monkey for you.'}
84
82
  jokes << %q{2. I went to the zoo the other day, there was only one dog in it, it was a shitzu.}
85
83
 
86
- disclaimer = Footer.new
84
+ disclaimer = Partial.new
87
85
  disclaimer << "According to a survey they were funny. I didn't make them."
88
86
 
89
87
  screen = Viewport.new
@@ -102,7 +100,7 @@ The most interesting function in my opinion is the callback that gets triggered
102
100
  screen = Viewport.new
103
101
 
104
102
  Console.set_console_resized_hook! do |size|
105
- notice = Content.new
103
+ notice = Partial.new
106
104
  notice << "You just resized your screen!\n\nNew size:"
107
105
  notice << size
108
106
  screen.draw notice
@@ -114,7 +112,10 @@ Remedy in the Wild
114
112
 
115
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.
116
114
 
117
- Here are a couple of projects that use many of Remedy's features:
115
+ Here are some projects that use Remedy:
116
+
117
+ - A screenreader-friendly code editor for blind and visually impaired programmers: [Viper](https://github.com/edhowland/viper)
118
+ - [The Official ElasticSearch Ruby Connector](https://github.com/elastic/connectors-ruby)
118
119
  - A multiplayer Yahtzee for web and console: [YahtzeeGame](https://github.com/ProgrammingPractice/YahtzeeGame)
119
120
  - Twitter/RSS/Facebook reader: [noizee](https://github.com/acook/noizee)
120
121
 
@@ -133,4 +134,3 @@ Contributing
133
134
  3. Commit your changes (`git commit -am 'Add some feature'`)
134
135
  4. Push to the branch (`git push origin my-new-feature`)
135
136
  5. Create new Pull Request
136
-
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "remedy", path: "../.."
@@ -7,7 +7,7 @@ include Remedy
7
7
  screen = Viewport.new
8
8
 
9
9
  Console.set_console_resized_hook! do |size|
10
- notice = Content.new
10
+ notice = Partial.new
11
11
  notice << "You just resized your screen!\n\nNew size:"
12
12
  notice << size
13
13
 
@@ -16,7 +16,7 @@ end
16
16
 
17
17
  user_input = Interaction.new "press any key to continue"
18
18
 
19
- joke = Content.new
19
+ joke = Partial.new
20
20
  joke << "Q: What's the difference between a duck?"
21
21
  joke << "A: Purple, because ice cream has no bones!"
22
22
 
@@ -24,14 +24,14 @@ screen.draw joke
24
24
 
25
25
  user_input.get_key
26
26
 
27
- title = Header.new
27
+ title = Partial.new
28
28
  title << "Someone Said These Were Good"
29
29
 
30
- jokes = Content.new
30
+ jokes = Partial.new
31
31
  jokes << %q{1. A woman gets on a bus with her baby. The bus driver says: 'Ugh, that's the ugliest baby I've ever seen!' The woman walks to the rear of the bus and sits down, fuming. She says to a man next to her: 'The driver just insulted me!' The man says: 'You go up there and tell him off. Go on, I'll hold your monkey for you.'}
32
32
  jokes << %q{2. I went to the zoo the other day, there was only one dog in it, it was a shitzu.}
33
33
 
34
- disclaimer = Footer.new
34
+ disclaimer = Partial.new
35
35
  disclaimer << "According to a survey they were funny. I didn't make them."
36
36
 
37
37
  screen.draw jokes, Size.new(0,0), title, disclaimer
@@ -39,7 +39,7 @@ screen.draw jokes, Size.new(0,0), title, disclaimer
39
39
  user_input.get_key
40
40
 
41
41
  ANSI.cursor.next_line!
42
- keys = Content.new
42
+ keys = Partial.new
43
43
  loop_demo = Interaction.new "press q to exit, or any other key to display that key's name\n"
44
44
  loop_demo.loop do |key|
45
45
  keys << key
@@ -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
@@ -47,7 +42,7 @@ class Menu
47
42
  # this creates a new content every time we draw
48
43
  # you may want to only create a new content/header/footer when they change
49
44
  # or create your own Partial subclass
50
- c = Content.new
45
+ c = Partial.new
51
46
  c << <<-CONTENT
52
47
 
53
48
  1. Do the thing
@@ -61,12 +56,12 @@ class Menu
61
56
 
62
57
  # headers are displayed the top of the viewport
63
58
  def header
64
- Header.new << "The time is: #{Time.now}"
59
+ Partial.new << "The time is: #{Time.now}"
65
60
  end
66
61
 
67
62
  # footers are displayed the bottom of the viewport
68
63
  def footer
69
- Footer.new << "Screen size: #{Console.size} You pressed: #{@last_key}"
64
+ Partial.new << "Screen size: #{Console.size} You pressed: #{@last_key}"
70
65
  end
71
66
  end
72
67
 
@@ -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
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.0'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -1,19 +1,14 @@
1
1
  require 'remedy/view'
2
2
  require 'remedy/size'
3
- require 'remedy/content'
4
3
  require 'remedy/console'
5
4
  require 'remedy/ansi'
6
5
 
7
6
  module Remedy
8
7
  class Viewport
9
- def draw content, center = Size.new(0,0), header = [], footer = []
10
- 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)
11
10
 
12
- if content.size.fits_into? range then
13
- viewable_content = content
14
- else
15
- viewable_content = content.excerpt *range
16
- end
11
+ viewable_content = content.excerpt *range
17
12
 
18
13
  view = View.new viewable_content, header, footer
19
14
 
@@ -21,19 +16,22 @@ module Remedy
21
16
  Console.output << view
22
17
  end
23
18
 
24
- def range_find partial, center, heightwidth
25
- row_size, col_size = heightwidth
26
- 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
27
24
 
28
- 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
29
27
 
30
- row_range = center_range center_row, row_size, row_limit
31
- col_range = center_range center_col, col_size, col_limit
32
28
  [row_range, col_range]
33
29
  end
34
30
 
35
- def content_size header, footer
36
- 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]
37
35
  size - trim
38
36
  end
39
37
 
@@ -41,20 +39,26 @@ module Remedy
41
39
  Size Console.size
42
40
  end
43
41
 
44
- def center_range center, width, limit
45
- 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
46
45
 
47
- if range_start + width > limit then
48
- range_start = limit - width
49
- end
46
+ # otherwise start looking at the scrolling offset, if any
50
47
 
51
- if range_start < 0 then
48
+ # clamp the offset within the possible range of the actual content
49
+ if offset < 0 then
52
50
  range_start = 0
51
+ elsif offset > actual then
52
+ range_start = actual
53
+ else
54
+ range_start = offset
53
55
  end
54
56
 
55
- range_end = range_start + width
57
+ # determine the subset of content that can be displayed
58
+ range_end = range_start + (available - offset)
56
59
 
57
60
  (range_start...range_end)
58
61
  end
62
+
59
63
  end
60
64
  end
data/lib/remedy.rb CHANGED
@@ -3,7 +3,7 @@ module Remedy
3
3
 
4
4
  def libs
5
5
  %w{
6
- version ansi characters console console_resize content header footer
6
+ version ansi characters console console_resize
7
7
  interaction key keyboard partial view viewport
8
8
  }
9
9
  end
@@ -3,11 +3,17 @@ require 'remedy/viewport'
3
3
 
4
4
  describe Remedy::Viewport do
5
5
  it 'should be able to execute the example code from the readme' do
6
- joke = ::Remedy::Content.new
6
+ @stdout = $stdout
7
+ joke = ::Remedy::Partial.new
7
8
  joke << "Q: What's the difference between a duck?"
8
9
  joke << "A: Purple, because ice cream has no bones!"
9
10
 
10
11
  screen = ::Remedy::Viewport.new
12
+ sio = StringIO.new
13
+ $stdout = sio
11
14
  screen.draw joke unless ENV['CI']
15
+ expect(sio.string).to include("ice cream")
16
+ ensure
17
+ $stdout = @stdout
12
18
  end
13
19
  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.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anthony M. Cook
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-22 00:00:00.000000000 Z
11
+ date: 2023-10-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -32,6 +32,8 @@ executables: []
32
32
  extensions: []
33
33
  extra_rdoc_files: []
34
34
  files:
35
+ - ".github/dependabot.yml"
36
+ - ".github/workflows/ci.yml"
35
37
  - ".gitignore"
36
38
  - ".ruby-gemset"
37
39
  - ".ruby-version"
@@ -40,16 +42,15 @@ files:
40
42
  - LICENSE.txt
41
43
  - README.markdown
42
44
  - Rakefile
45
+ - examples/from_readme/Gemfile
43
46
  - examples/from_readme/readme.rb
47
+ - examples/menu/Gemfile
44
48
  - examples/menu/menu.rb
45
49
  - lib/remedy.rb
46
50
  - lib/remedy/ansi.rb
47
51
  - lib/remedy/characters.rb
48
52
  - lib/remedy/console.rb
49
53
  - lib/remedy/console_resize.rb
50
- - lib/remedy/content.rb
51
- - lib/remedy/footer.rb
52
- - lib/remedy/header.rb
53
54
  - lib/remedy/interaction.rb
54
55
  - lib/remedy/key.rb
55
56
  - lib/remedy/keyboard.rb
@@ -68,7 +69,7 @@ homepage: http://github.com/acook/remedy
68
69
  licenses:
69
70
  - MIT
70
71
  metadata: {}
71
- post_install_message:
72
+ post_install_message:
72
73
  rdoc_options: []
73
74
  require_paths:
74
75
  - lib
@@ -83,8 +84,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
84
  - !ruby/object:Gem::Version
84
85
  version: '0'
85
86
  requirements: []
86
- rubygems_version: 3.1.2
87
- signing_key:
87
+ rubygems_version: 3.3.7
88
+ signing_key:
88
89
  specification_version: 4
89
90
  summary: Pure Ruby Console Interaction Library
90
91
  test_files:
@@ -1,4 +0,0 @@
1
- require 'remedy/partial'
2
-
3
- class Remedy::Content < Remedy::Partial
4
- end
data/lib/remedy/footer.rb DELETED
@@ -1,4 +0,0 @@
1
- require 'remedy/partial'
2
-
3
- class Remedy::Footer < Remedy::Partial
4
- end
data/lib/remedy/header.rb DELETED
@@ -1,4 +0,0 @@
1
- require 'remedy/partial'
2
-
3
- class Remedy::Header < Remedy::Partial
4
- end