terminal-scroll-area 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 40c9d9bbc20a2507effd83bcb58b1079d900fc44a7d06ca84353ff1d9aa197b2
4
+ data.tar.gz: 7d86e009629484903f837f0546d93dea58ad0b7753aeff9fa03012a89f7e83a9
5
+ SHA512:
6
+ metadata.gz: c23164544666966a7b5ba12aca35fe911de61a084df75bb1ea620d1d8d93aab8314293c633e3725af939dfe00084b575ded9d676e71d37f2ab1bee77e0ec4488
7
+ data.tar.gz: 59cfee4ad6c585515b44e897f8047e5fd282112c950c040f9db283b02bb21feca9e85ec78a63f9aab6d12f5e5d66227ca65fd0b0b1a222b8d49284b26dc60361
@@ -0,0 +1,82 @@
1
+ # Terminal Scroll Area
2
+
3
+ This gem lets the user display large text on terminal by creating a scroll area in which only a specified portion of the text is displayed at a time. This portion can be moved to reveal other parts of the text, analogous to a GUI scroll area, or a more general purpose pager. This gem is useful when your program needs to display a large amount of text that may not fit into the screen.
4
+
5
+ The `ScrollArea` class, which is not interactive, does not use Curses or a similar screen management library. The `InteractiveScrollArea` class does not rely on the Curses library and instead uses the [TTY toolkit](https://github.com/piotrmurach/tty), which has cross platform support and support for many types of terminals/terminal emulators. Therefore this gem should also have the same level of support.
6
+
7
+ # Usage
8
+
9
+ ## `ScrollArea` class
10
+
11
+ - Simple scroll area which lets you programmatically scroll the content in all directions.
12
+ - Initialise:
13
+
14
+ ```rb
15
+ # Only display 5 lines at a time with
16
+ # 5 characters in each line.
17
+ width = 5
18
+ height = 5
19
+ scroll = ScrollArea.new(width, height)
20
+ ```
21
+
22
+ - Set the content that the scroll area will contain:
23
+
24
+ ```rb
25
+ # Set content all at once:
26
+ scroll.content = "some text"
27
+
28
+ # Or use add_string/add_line:
29
+ scroll.add_string("some string")
30
+
31
+ # Same as add_string, but adds a newline
32
+ # after the string
33
+ scroll.add_line("some line")
34
+ ```
35
+
36
+ - Render scroll area to get the portion of the entire content which is in view:
37
+
38
+ ```rb
39
+ # Render and print the currently visible
40
+ # portion of the text.
41
+ print(scroll.render)
42
+ ```
43
+
44
+ - Scroll in all directions to reveal other portions:
45
+
46
+ ```rb
47
+ # also available:
48
+ # - scroll_down
49
+ # - scroll_left
50
+ # - scroll_right
51
+ scroll.scroll_up
52
+ ```
53
+
54
+ - Scroll area lets you access some values you may find useful:
55
+
56
+ ```rb
57
+ # The starting coordinates of the window which is displayed.
58
+ scroll.start_x
59
+ scroll.start_y
60
+
61
+ # The ending coordinates of the window which is displayed.
62
+ scroll.end_x
63
+ scroll.end_y
64
+ ```
65
+
66
+ ## `InteractiveScrollArea`
67
+
68
+ - Regular `ScrollArea` lets you scroll the content with `scroll_<direction>` methods. `InteractiveScrollArea` displays an interactive scroll area where the user can use arrow keys to control scrolling of the content (e.g. up arrow scrolls up, etc.).
69
+ - This class will automatically print a new rendering of the area after user has triggered a scroll event by pressing a key. The previously printed rendering is removed and the updated rendering is printed in the same area, thereby giving the feeling of interactivity.
70
+
71
+ ```rb
72
+ width = 5
73
+ height = 5
74
+ interactive = InteractiveScrollArea(width, height)
75
+
76
+ # add_string and add_line are also available.
77
+ interactive.content = "some text"
78
+
79
+ # Starts a loop, allowing user to use arrow keys to
80
+ # scroll the content. Press Ctrl + C to exit.
81
+ interactive.scroll
82
+ ```
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'terminal-scroll-area/scroll_area'
4
+ require_relative 'terminal-scroll-area/interactive_scroll_area'
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tty-reader'
4
+ require 'tty-cursor'
5
+ require_relative 'scroll_area'
6
+
7
+ # Interactice scroll area which scrolls and reprints
8
+ # the content in response to user pressing arrow keys.
9
+ class InteractiveScrollArea
10
+ attr_reader :content
11
+ attr_accessor :width, :height, :scroll_area
12
+
13
+ def initialize(width, height)
14
+ @width = width
15
+ @height = height
16
+
17
+ @scroll_area = ScrollArea.new(@width, @height)
18
+
19
+ @reader = TTY::Reader.new(interrupt: :exit)
20
+ @reader.subscribe(self)
21
+ end
22
+
23
+ def scroll
24
+ print_in_place(@scroll_area.render)
25
+ TTY::Cursor.invisible do
26
+ loop do
27
+ @reader.read_keypress
28
+ end
29
+ end
30
+ end
31
+
32
+ def content=(new_content)
33
+ @scroll_area.content = new_content
34
+ end
35
+
36
+ def add_string(string)
37
+ @scroll_area.add_string(string)
38
+ end
39
+
40
+ def add_line(line)
41
+ @scroll_area.add_line(line)
42
+ end
43
+
44
+ def keydown(_event)
45
+ @scroll_area.scroll_down
46
+ print_in_place(@scroll_area.render)
47
+ end
48
+
49
+ def keyup(_event)
50
+ @scroll_area.scroll_up
51
+ print_in_place(@scroll_area.render)
52
+ end
53
+
54
+ def keyright(_event)
55
+ @scroll_area.scroll_right
56
+ print_in_place(@scroll_area.render)
57
+ end
58
+
59
+ def keyleft(_event)
60
+ @scroll_area.scroll_left
61
+ print_in_place(@scroll_area.render)
62
+ end
63
+
64
+ private
65
+
66
+ def print_in_place(text)
67
+ cursor = TTY::Cursor
68
+
69
+ # Scrolling down is needed if there are less lines under
70
+ # the terminal prompt than the content height. Or else, clearing
71
+ # lines upwards by the content height will remove the prompt as well.
72
+ in_place = TTY::Cursor.scroll_down * (@height - 1)
73
+ in_place << cursor.clear_lines(@height, :up)
74
+ in_place << cursor.save
75
+ in_place << text
76
+ in_place << cursor.restore
77
+
78
+ print(in_place)
79
+ end
80
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Scroll area which only shows a specific area of the content
4
+ # it holds at a time. Able to scroll area in all directions
5
+ # to show a different area of the content.
6
+ class ScrollArea
7
+ attr_reader :start_x, :start_y, :content
8
+ attr_accessor :width, :height
9
+
10
+ def initialize(width, height)
11
+ @width = width
12
+ @height = height
13
+ @start_x = 0
14
+ @start_y = 0
15
+ @content = ''
16
+ update_content_dimensions
17
+ end
18
+
19
+ def render
20
+ crop_text(@content, @start_x, @start_y, end_x, end_y)
21
+ end
22
+
23
+ def content=(new_content)
24
+ @content = new_content
25
+ update_content_dimensions
26
+ end
27
+
28
+ def add_string(string)
29
+ self.content += string
30
+ end
31
+
32
+ def add_line(line)
33
+ self.content += "#{line}\n"
34
+ end
35
+
36
+ def scroll_up
37
+ return if @line_count < @height
38
+
39
+ @start_y -= 1 if @start_y.positive?
40
+ end
41
+
42
+ def scroll_down
43
+ return if @line_count < @height
44
+
45
+ @start_y += 1 if end_y < (@line_count - 1)
46
+ end
47
+
48
+ def scroll_left
49
+ return if @col_count < @width
50
+
51
+ @start_x -= 1 if @start_x >= 1
52
+ end
53
+
54
+ def scroll_right
55
+ return if @col_count < @width
56
+
57
+ @start_x += 1 if end_x < (@col_count - 1)
58
+ end
59
+
60
+ def end_x
61
+ @start_x + (@width - 1)
62
+ end
63
+
64
+ def end_y
65
+ @start_y + (@height - 1)
66
+ end
67
+
68
+ private
69
+
70
+ def update_content_dimensions
71
+ @line_count = @content.split("\n").length
72
+ @col_count = @content.split("\n").map(&:length).max
73
+ end
74
+
75
+ def crop_text(text, x_start, y_start, x_end, y_end)
76
+ return '' if x_start >= @col_count || y_start >= @line_count
77
+
78
+ lines = text.split("\n")
79
+ lines = lines[y_start..y_end]
80
+ lines = lines.map { |line| line[x_start..x_end] }
81
+ lines.join("\n")
82
+ end
83
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: terminal-scroll-area
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ilkut Kutlar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-06-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: tty-cursor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.7.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.7.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: tty-reader
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.7.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.7.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.9'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.9'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.82.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.82.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.18.5
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.18.5
83
+ description: This gem lets user display large text on terminal by creating a scroll
84
+ area in which only a specified portion of the text is displayed at a time. This
85
+ portion can be moved to reveal other parts of the text, analogous to a GUI scroll
86
+ area.
87
+ email:
88
+ - ilkutkutlar@gmail.com
89
+ executables: []
90
+ extensions: []
91
+ extra_rdoc_files: []
92
+ files:
93
+ - README.md
94
+ - lib/terminal-scroll-area.rb
95
+ - lib/terminal-scroll-area/interactive_scroll_area.rb
96
+ - lib/terminal-scroll-area/scroll_area.rb
97
+ homepage: https://github.com/ilkutkutlar/terminal-scroll-area
98
+ licenses:
99
+ - MIT
100
+ metadata: {}
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: 2.0.0
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubygems_version: 3.0.3
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: Scroll area to display large text on terminal
120
+ test_files: []