tty_string 0.1.0 → 0.2.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
- SHA1:
3
- metadata.gz: 5cf9c99684d1bffc4b5238d85a0fbddc6c228a92
4
- data.tar.gz: 29daa63edffa32d87215419a32c0f3eb06511648
2
+ SHA256:
3
+ metadata.gz: a98f1f00566e4802bab20aa02326c6c53f9bbd164bbd5a499f64afc5a84f88cb
4
+ data.tar.gz: aa22c08116ffc776f98342bf7f8704cb5bfff7ec477fbe237d7405d1ae75752d
5
5
  SHA512:
6
- metadata.gz: c0184931cc63e842676e467f9cf1e3262f97a3e191f690bc100e075f389cdd54e3d94d09295da58a2e23a97b9f27836cd3eaf6772a67079184b1fc8030cd05ac
7
- data.tar.gz: 5804b7bcf35cb28a18feeb330662cac534b307badd16f2ebd5e138a772fcd8cf4743702181d33a208bf6b20f8d03013ac0f77fae7e1faba4eb1745bbb2687296
6
+ metadata.gz: e2f47e040687ea392c87784ffbe45cefe76c0dc0c5c644e651ecdc349f7d57a140c869dfd685492e8f02b430b3b3e92a3121d3f67edc3e9bd7109cd2cf979fba
7
+ data.tar.gz: 59ddb4338dc11b483666497ea417a30f9857172a81e3c39271b1585d94d40f1738a3f426600e037f50d110f5abeeab36d6f0b62b9495bb4207802c5333ccb181
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # v0.2.0
2
+ - Stricter rendering because it turns out terminals are randomly permissive
3
+ - removed support for ruby 2.3
4
+ - added \e[S and \e[T handling
5
+
6
+ # v0.1.0
7
+ - Initial Release
data/Gemfile CHANGED
@@ -2,7 +2,5 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
- git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
-
7
5
  # Specify your gem's dependencies in tty_string.gemspec
8
6
  gemspec
data/README.md CHANGED
@@ -1,26 +1,35 @@
1
1
  # TTYString
2
2
 
3
- Render a string like your terminal does by parsing ANSI TTY codes.
3
+ [![Build Status](https://travis-ci.org/robotdana/tty_string.svg?branch=master)](https://travis-ci.org/robotdana/tty_string)
4
+
5
+ Render a string like your terminal does by (narrowly) parsing ANSI TTY codes.
4
6
  This is useful for testing CLI's
5
7
 
8
+ Various terminals are wildly variously permissive with what they accept,
9
+ so this doesn't even try to cover all possible cases,
10
+ instead it covers the narrowest possible case, and leaves the codes in place when unrecognised
11
+
6
12
  Supported codes
7
13
 
8
- - \b
9
- - \e[A
10
- - \e[B
11
- - \e[C
12
- - \e[D
13
- - \e[E
14
- - \e[F
15
- - \e[G
16
- - \e[H
17
- - \e[J
18
- - \e[K
19
- - \e[f
20
- - \e[m
21
- - \n
22
- - \r
23
- - \t
14
+ - `\a` # BEL, just removed.
15
+ - `\b` # backspace
16
+ - `\n` # newline
17
+ - `\r` # return, jump to the start of the line
18
+ - `\t` # tab, move to the next multiple-of-8 column
19
+ - `\e[nA` # move up n lines, default: 1
20
+ - `\e[nB` # move down n lines, default: 1
21
+ - `\e[nC` # move right n columns, default: 1
22
+ - `\e[nD` # move left n columns, default: 1
23
+ - `\e[nE` # move down n lines, and to the start of the line, default: 1
24
+ - `\e[nF` # move up n lines, and to the start of the line, default: 1
25
+ - `\e[nG` # jump to column to n
26
+ - `\e[n;mH` # jump to row n, column m, default: 1,1
27
+ - `\e[nJ` # n=0: clear the screen forward, n=1: clear backward, n=2 or 3: clear the screen. default 0
28
+ - `\e[nK` # n=0: clear the line forward, n=1: clear the line backward, n=2: clear the line. default 0
29
+ - `\e[n;mf` # jump to row n, column m, default: 1,1
30
+ - `\e[m` # styling codes, optionally suppressed with clear_style: false
31
+ - `\e[nS` # scroll down n rows, default 1
32
+ - `\e[nT` # scroll up n rows, default 1
24
33
 
25
34
  ## Installation
26
35
 
@@ -40,17 +49,20 @@ Or install it yourself as:
40
49
 
41
50
  ## Usage
42
51
 
43
- ```
44
- TTYString.new("th\ta string\e[3Gis is").to_s => "this is a string"
52
+ ```ruby
53
+ TTYString.new("th\ta string\e[3Gis is").to_s
54
+ => "this is a string"
45
55
  ```
46
56
 
47
57
  Styling information is suppressed by default:
48
- ```
49
- TTYString.new("th\ta \e[31mstring\e[0m\e[3Gis is", clear_style: false).to_s => "this is a string"
58
+ ```ruby
59
+ TTYString.new("th\ta \e[31mstring\e[0m\e[3Gis is").to_s
60
+ => "this is a string"
50
61
  ```
51
62
  But can be passed through:
52
- ```
53
- TTYString.new("th\ta \e[31mstring\e[0m\e[3Gis is", clear_style: false).to_s => "this is a \e[31mstring\e[0m"
63
+ ```ruby
64
+ TTYString.new("th\ta \e[31mstring\e[0m\e[3Gis is", clear_style: false).to_s
65
+ => "this is a \e[31mstring\e[0m"
54
66
  ```
55
67
 
56
68
  ## Development
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TTYString
4
+ class Code
5
+ class << self
6
+ def descendants
7
+ @@descendants
8
+ end
9
+
10
+ def inherited(klass)
11
+ @@descendants ||= [] # rubocop:disable Style/ClassVars I want it to be shared between subclasses.
12
+ @@descendants << klass
13
+ @@descendants.uniq!
14
+ end
15
+
16
+ def render(parser)
17
+ return unless match?(parser)
18
+
19
+ new(parser).action(*args(parser))
20
+
21
+ true
22
+ end
23
+
24
+ def char(value = nil)
25
+ @char = value if value
26
+ @char ||= name.split('::').last
27
+ end
28
+
29
+ private
30
+
31
+ def re
32
+ @re ||= /#{char}/.freeze
33
+ end
34
+
35
+ def args(_scanner)
36
+ []
37
+ end
38
+
39
+ def match?(parser)
40
+ parser.skip(re)
41
+ end
42
+ end
43
+
44
+ def initialize(parser)
45
+ @parser = parser
46
+ end
47
+
48
+ private
49
+
50
+ attr_reader :parser
51
+
52
+ def action; end
53
+
54
+ def screen
55
+ parser.screen
56
+ end
57
+
58
+ def cursor
59
+ parser.cursor
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'code'
4
+ require_relative 'csi_code'
5
+
6
+ class TTYString
7
+ class Code
8
+ class SlashA < TTYString::Code
9
+ char "\a"
10
+ end
11
+
12
+ class SlashB < TTYString::Code
13
+ char "\b"
14
+
15
+ def self.match?(scanner)
16
+ # can't use `scan(/\b/)` because it matches everything
17
+ return false unless scanner.peek(1) == "\b"
18
+
19
+ scanner.pos += 1
20
+ true
21
+ end
22
+
23
+ def action
24
+ cursor.left
25
+ screen.clear_at_cursor
26
+ end
27
+ end
28
+
29
+ class SlashN < TTYString::Code
30
+ char "\n"
31
+
32
+ def action
33
+ cursor.down
34
+ cursor.col = 0
35
+ screen.write('')
36
+ end
37
+ end
38
+
39
+ class SlashR < TTYString::Code
40
+ char "\r"
41
+
42
+ def action
43
+ cursor.col = 0
44
+ end
45
+ end
46
+
47
+ class SlashT < TTYString::Code
48
+ char "\t"
49
+
50
+ def action
51
+ cursor.right(8 - (cursor.col % 8))
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'code'
4
+
5
+ class TTYString
6
+ class CSICode < TTYString::Code
7
+ class << self
8
+ def default_arg(value = nil)
9
+ @default_arg ||= value
10
+ @default_arg || 1
11
+ end
12
+
13
+ private
14
+
15
+ def match?(parser)
16
+ parser.scan(re)
17
+ end
18
+
19
+ def args(parser)
20
+ parser.matched.slice(2..-2).split(';')
21
+ .map { |n| n.empty? ? default_arg : n.to_i }
22
+ end
23
+
24
+ def re
25
+ @re ||= /\e\[#{args_re}#{char}/
26
+ end
27
+
28
+ def args_re
29
+ case max_args
30
+ when 1 then /#{arg_re}?/
31
+ when nil then /(#{arg_re}?(;#{arg_re})*)?/
32
+ else /(#{arg_re}?(;#{arg_re}){0,#{max_args - 1}})?/
33
+ end
34
+ end
35
+
36
+ def arg_re
37
+ /\d*/
38
+ end
39
+
40
+ def max_args
41
+ @max_args ||= begin
42
+ params = instance_method(:action).parameters
43
+ return if params.assoc(:rest)
44
+
45
+ params.length
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ TTYString::Code.descendants.pop
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'csi_code'
4
+
5
+ class TTYString
6
+ class CSICode
7
+ class A < TTYString::CSICode
8
+ def action(rows = 1)
9
+ cursor.up(rows)
10
+ end
11
+ end
12
+
13
+ class B < TTYString::CSICode
14
+ def action(rows = 1)
15
+ cursor.down(rows)
16
+ end
17
+ end
18
+
19
+ class C < TTYString::CSICode
20
+ def action(cols = 1)
21
+ cursor.right(cols)
22
+ end
23
+ end
24
+
25
+ class D < TTYString::CSICode
26
+ def action(cols = 1)
27
+ cursor.left(cols)
28
+ end
29
+ end
30
+
31
+ class E < TTYString::CSICode
32
+ def action(rows = 1)
33
+ cursor.down(rows)
34
+ cursor.col = 0
35
+ end
36
+ end
37
+
38
+ class F < TTYString::CSICode
39
+ def action(rows = 1)
40
+ cursor.up(rows)
41
+ cursor.col = 0
42
+ end
43
+ end
44
+
45
+ class G < TTYString::CSICode
46
+ def action(col = 1)
47
+ # cursor is zero indexed, arg is 1 indexed
48
+ cursor.col = col.to_i - 1
49
+ end
50
+ end
51
+
52
+ class H < TTYString::CSICode
53
+ def action(row = 1, col = 1)
54
+ # cursor is zero indexed, arg is 1 indexed
55
+ cursor.row = row.to_i - 1
56
+ cursor.col = col.to_i - 1
57
+ end
58
+ end
59
+
60
+ class LowF < TTYString::CSICode::H
61
+ char 'f'
62
+ end
63
+
64
+ class J < TTYString::CSICode
65
+ default_arg 0
66
+
67
+ def self.args_re
68
+ /[0-3]?/
69
+ end
70
+
71
+ def action(mode = 0)
72
+ # :nocov: else won't ever be called. don't worry about it
73
+ case mode
74
+ # :nocov:
75
+ when 0 then screen.clear_forward
76
+ when 1 then screen.clear_backward
77
+ when 2, 3 then screen.clear
78
+ end
79
+ end
80
+ end
81
+
82
+ class K < TTYString::CSICode
83
+ default_arg 0
84
+
85
+ def self.arg_re
86
+ /[0-2]?/
87
+ end
88
+
89
+ def action(mode = 0)
90
+ # :nocov: else won't ever be called. don't worry about it
91
+ case mode
92
+ # :nocov:
93
+ when 0 then screen.clear_line_forward
94
+ when 1 then screen.clear_line_backward
95
+ when 2 then screen.clear_line
96
+ end
97
+ end
98
+ end
99
+
100
+ class LowM < TTYString::CSICode
101
+ char 'm'
102
+
103
+ def self.arg_re
104
+ # 0-255
105
+ /(\d|\d\d|1\d\d|2[0-4]\d|25[0-5])?/
106
+ end
107
+
108
+ def self.render(renderer)
109
+ super if renderer.clear_style
110
+ end
111
+
112
+ def action(*args); end
113
+ end
114
+
115
+ class S < TTYString::CSICode
116
+ def action(rows = 1)
117
+ rows.times { screen.scroll_up }
118
+ end
119
+ end
120
+
121
+ class T < TTYString::CSICode
122
+ def action(rows = 1)
123
+ rows.times { screen.scroll_down }
124
+ end
125
+ end
126
+ end
127
+ end
@@ -11,40 +11,28 @@ class TTYString
11
11
  end
12
12
 
13
13
  def row=(value)
14
- @row = value.to_i
14
+ @row = value
15
15
  @row = 0 if @row.negative?
16
16
  end
17
17
 
18
18
  def col=(value)
19
- @col = value.to_i
19
+ @col = value
20
20
  @col = 0 if @col.negative?
21
21
  end
22
22
 
23
23
  def left(count = 1)
24
- count = count.to_i
25
- raise ArgumentError if count.negative?
26
-
27
24
  self.col -= count
28
25
  end
29
26
 
30
27
  def up(count = 1)
31
- count = count.to_i
32
- raise ArgumentError if count.negative?
33
-
34
28
  self.row -= count
35
29
  end
36
30
 
37
31
  def down(count = 1)
38
- count = count.to_i
39
- raise ArgumentError unless count >= 0
40
-
41
32
  self.row += count
42
33
  end
43
34
 
44
35
  def right(count = 1)
45
- count = count.to_i
46
- raise ArgumentError unless count >= 0
47
-
48
36
  self.col += count
49
37
  end
50
38
 
@@ -1,82 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'strscan'
4
- require_relative 'renderer'
4
+ require_relative 'code_definitions'
5
+ require_relative 'csi_code_definitions'
6
+
7
+ require_relative 'screen'
5
8
 
6
9
  class TTYString
7
10
  # Reads the text string a
8
11
  class Parser < StringScanner
9
- def render(clear_style: true)
12
+ attr_accessor :clear_style
13
+ attr_reader :screen
14
+
15
+ def render
10
16
  reset
11
- @clear_style = clear_style
12
- @renderer = Renderer.new
17
+ @screen = Screen.new
13
18
  read until eos?
14
- renderer.to_s
19
+ screen.to_s
15
20
  end
16
21
 
17
- private
22
+ def cursor
23
+ screen.cursor
24
+ end
18
25
 
19
- attr_reader :renderer
20
- attr_reader :clear_style
26
+ private
21
27
 
22
28
  def write(string)
23
- renderer.write(string)
29
+ screen.write(string)
24
30
  end
25
31
 
26
32
  def read
27
- text || slash_n || slash_r || slash_t || slash_b || slash_e
28
- end
29
-
30
- def text
31
- write(matched) if scan(text_regexp)
32
- end
33
-
34
- def slash_n
35
- renderer.slash_n if skip(/\n/)
36
- end
37
-
38
- def slash_r
39
- renderer.slash_r if skip(/\r/)
40
- end
41
-
42
- def slash_t
43
- renderer.slash_t if skip(/\t/)
44
- end
45
-
46
- def slash_b
47
- # can't use `scan(/\b/)` because it matches everything
48
- return unless peek(1) == "\b"
49
-
50
- self.pos += 1
51
- renderer.slash_b
52
- end
53
-
54
- def slash_e
55
- return unless scan(csi_regexp)
56
-
57
- args = matched.slice(2..-2).split(';')
58
- command = matched.slice(-1)
59
- render_csi(:"csi_#{command}", *args)
60
- end
61
-
62
- def csi_regexp
63
- @csi_regexp ||= Regexp.new("\e#{csi_pattern}")
64
- end
65
-
66
- def csi_pattern
67
- "\\[(\\d+;?|;)*[ABCDEFGHJKf#{'m' if clear_style}]"
68
- end
69
-
70
- def text_regexp
71
- @text_regexp ||= Regexp.new("[^\b\t\r\n\e]|\e(?!#{csi_pattern})")
33
+ TTYString::Code.descendants.any? { |c| c.render(self) } || default
72
34
  end
73
35
 
74
- def render_csi(method, *args)
75
- method = renderer.method(method)
76
- params = method.parameters
77
- args = args.take(params.length) unless params.assoc(:rest)
78
- args = [] if args.all?(&:empty?)
79
- method.call(*args)
36
+ def default
37
+ write(getch)
80
38
  end
81
39
  end
82
40
  end
@@ -46,6 +46,16 @@ class TTYString
46
46
  @screen = []
47
47
  end
48
48
 
49
+ def scroll_up
50
+ screen.push([])
51
+ screen.shift
52
+ end
53
+
54
+ def scroll_down
55
+ screen.unshift([])
56
+ screen.pop
57
+ end
58
+
49
59
  def clear_lines_before
50
60
  screen.fill([], 0...row)
51
61
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class TTYString
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
5
5
  end
data/lib/tty_string.rb CHANGED
@@ -7,11 +7,11 @@ require_relative 'tty_string/parser'
7
7
  class TTYString
8
8
  def initialize(input_string, clear_style: true)
9
9
  @parser = Parser.new(input_string)
10
- @clear_style = clear_style
10
+ @parser.clear_style = clear_style
11
11
  end
12
12
 
13
13
  def to_s
14
- parser.render(clear_style: clear_style)
14
+ parser.render
15
15
  end
16
16
 
17
17
  private
data/tty_string.gemspec CHANGED
@@ -11,21 +11,25 @@ Gem::Specification.new do |spec|
11
11
  spec.email = ['robot@dana.sh']
12
12
 
13
13
  spec.summary = 'Render a string using ANSI TTY codes'
14
- spec.homepage = "https://github.com/robotdana/tty_string"
14
+ spec.homepage = 'https://github.com/robotdana/tty_string'
15
15
  spec.license = 'MIT'
16
16
 
17
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
- f.match(%r{^(test|spec|features|\.?rubocop|\.travis|\.git|\.rspec)/})
19
- end
20
- spec.bindir = 'exe'
21
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
17
+ spec.files = Dir.glob('{lib}/**/*') + %w{
18
+ CHANGELOG.md
19
+ Gemfile
20
+ LICENSE.txt
21
+ README.md
22
+ tty_string.gemspec
23
+ }
24
+ spec.required_ruby_version = '>= 2.4'
22
25
  spec.require_paths = ['lib']
23
26
 
24
- spec.add_development_dependency 'bundler', '~> 1.16'
25
- spec.add_development_dependency 'pry', '~> 0.12.2'
27
+ spec.add_development_dependency 'bundler', '~> 2.0'
28
+ spec.add_development_dependency 'pry', '~> 0.12'
26
29
  spec.add_development_dependency 'rake', '~> 10.0'
27
30
  spec.add_development_dependency 'rspec', '~> 3.0'
28
- spec.add_development_dependency 'rubocop', '~> 0.74.0'
29
- spec.add_development_dependency 'rubocop-performance', '~> 1.4.1'
30
- spec.add_development_dependency 'rubocop-rspec', '~> 1.35.0'
31
+ spec.add_development_dependency 'rubocop', '~> 0.74'
32
+ spec.add_development_dependency 'rubocop-performance', '~> 1.4'
33
+ spec.add_development_dependency 'rubocop-rspec', '~> 1.35'
34
+ spec.add_development_dependency 'simplecov', '~> 0.18.5'
31
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tty_string
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dana Sherson
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-21 00:00:00.000000000 Z
11
+ date: 2020-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.16'
19
+ version: '2.0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.16'
26
+ version: '2.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: pry
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.12.2
33
+ version: '0.12'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.12.2
40
+ version: '0.12'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -72,42 +72,56 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 0.74.0
75
+ version: '0.74'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 0.74.0
82
+ version: '0.74'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rubocop-performance
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 1.4.1
89
+ version: '1.4'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 1.4.1
96
+ version: '1.4'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rubocop-rspec
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 1.35.0
103
+ version: '1.35'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: 1.35.0
110
+ version: '1.35'
111
+ - !ruby/object:Gem::Dependency
112
+ name: simplecov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 0.18.5
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.18.5
111
125
  description:
112
126
  email:
113
127
  - robot@dana.sh
@@ -115,22 +129,17 @@ executables: []
115
129
  extensions: []
116
130
  extra_rdoc_files: []
117
131
  files:
118
- - ".gitignore"
119
- - ".gitmodules"
120
- - ".rspec"
121
- - ".rubocop.yml"
122
- - ".travis.yml"
132
+ - CHANGELOG.md
123
133
  - Gemfile
124
- - Gemfile.lock
125
134
  - LICENSE.txt
126
135
  - README.md
127
- - Rakefile
128
- - bin/console
129
- - bin/setup
130
136
  - lib/tty_string.rb
137
+ - lib/tty_string/code.rb
138
+ - lib/tty_string/code_definitions.rb
139
+ - lib/tty_string/csi_code.rb
140
+ - lib/tty_string/csi_code_definitions.rb
131
141
  - lib/tty_string/cursor.rb
132
142
  - lib/tty_string/parser.rb
133
- - lib/tty_string/renderer.rb
134
143
  - lib/tty_string/screen.rb
135
144
  - lib/tty_string/version.rb
136
145
  - tty_string.gemspec
@@ -146,15 +155,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
146
155
  requirements:
147
156
  - - ">="
148
157
  - !ruby/object:Gem::Version
149
- version: '0'
158
+ version: '2.4'
150
159
  required_rubygems_version: !ruby/object:Gem::Requirement
151
160
  requirements:
152
161
  - - ">="
153
162
  - !ruby/object:Gem::Version
154
163
  version: '0'
155
164
  requirements: []
156
- rubyforge_project:
157
- rubygems_version: 2.5.2.1
165
+ rubygems_version: 3.1.2
158
166
  signing_key:
159
167
  specification_version: 4
160
168
  summary: Render a string using ANSI TTY codes
data/.gitignore DELETED
@@ -1,11 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
-
10
- # rspec failure tracking
11
- .rspec_status
data/.gitmodules DELETED
@@ -1,3 +0,0 @@
1
- [submodule "rubocop_yml"]
2
- path = rubocop_yml
3
- url = https://github.com/robotdana/rubocop_yml.git
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --color
3
- --require spec_helper
data/.rubocop.yml DELETED
@@ -1 +0,0 @@
1
- rubocop_yml/rubocop.yml
data/.travis.yml DELETED
@@ -1,5 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.5.1
5
- before_install: gem install bundler -v 1.16.0
data/Gemfile.lock DELETED
@@ -1,63 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- tty_string (0.1.0)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- ast (2.4.0)
10
- coderay (1.1.2)
11
- diff-lcs (1.3)
12
- jaro_winkler (1.5.3)
13
- method_source (0.9.2)
14
- parallel (1.17.0)
15
- parser (2.6.4.1)
16
- ast (~> 2.4.0)
17
- pry (0.12.2)
18
- coderay (~> 1.1.0)
19
- method_source (~> 0.9.0)
20
- rainbow (3.0.0)
21
- rake (10.5.0)
22
- rspec (3.8.0)
23
- rspec-core (~> 3.8.0)
24
- rspec-expectations (~> 3.8.0)
25
- rspec-mocks (~> 3.8.0)
26
- rspec-core (3.8.2)
27
- rspec-support (~> 3.8.0)
28
- rspec-expectations (3.8.4)
29
- diff-lcs (>= 1.2.0, < 2.0)
30
- rspec-support (~> 3.8.0)
31
- rspec-mocks (3.8.1)
32
- diff-lcs (>= 1.2.0, < 2.0)
33
- rspec-support (~> 3.8.0)
34
- rspec-support (3.8.2)
35
- rubocop (0.74.0)
36
- jaro_winkler (~> 1.5.1)
37
- parallel (~> 1.10)
38
- parser (>= 2.6)
39
- rainbow (>= 2.2.2, < 4.0)
40
- ruby-progressbar (~> 1.7)
41
- unicode-display_width (>= 1.4.0, < 1.7)
42
- rubocop-performance (1.4.1)
43
- rubocop (>= 0.71.0)
44
- rubocop-rspec (1.35.0)
45
- rubocop (>= 0.60.0)
46
- ruby-progressbar (1.10.1)
47
- unicode-display_width (1.6.0)
48
-
49
- PLATFORMS
50
- ruby
51
-
52
- DEPENDENCIES
53
- bundler (~> 1.16)
54
- pry (~> 0.12.2)
55
- rake (~> 10.0)
56
- rspec (~> 3.0)
57
- rubocop (~> 0.74.0)
58
- rubocop-performance (~> 1.4.1)
59
- rubocop-rspec (~> 1.35.0)
60
- tty_string!
61
-
62
- BUNDLED WITH
63
- 1.16.0
data/Rakefile DELETED
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/gem_tasks'
4
- require 'rspec/core/rake_task'
5
-
6
- RSpec::Core::RakeTask.new(:spec)
7
-
8
- task default: :spec
data/bin/console DELETED
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require 'bundler/setup'
5
- require 'tty_string'
6
-
7
- # You can add fixtures and/or initialization code here to make experimenting
8
- # with your gem easier. You can also use a different console, if you like.
9
-
10
- # (If you use this, don't forget to add pry to your Gemfile!)
11
- # require "pry"
12
- # Pry.start
13
-
14
- require 'irb'
15
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
@@ -1,104 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'screen'
4
- class TTYString
5
- # turns the text string into screen instructions
6
- class Renderer
7
- attr_reader :screen
8
-
9
- def initialize
10
- @screen = Screen.new
11
- end
12
-
13
- def to_s
14
- screen.to_s
15
- end
16
-
17
- def write(string)
18
- screen.write(string)
19
- end
20
-
21
- # rubocop:disable Naming/MethodName
22
- def csi_A(rows = 1)
23
- cursor.up(rows)
24
- end
25
-
26
- def csi_B(rows = 1)
27
- cursor.down(rows)
28
- end
29
-
30
- def csi_C(cols = 1)
31
- cursor.right(cols)
32
- end
33
-
34
- def csi_D(cols = 1)
35
- cursor.left(cols)
36
- end
37
-
38
- def csi_E(rows = 1)
39
- cursor.down(rows)
40
- cursor.col = 0
41
- end
42
-
43
- def csi_F(rows = 1)
44
- cursor.up(rows)
45
- cursor.col = 0
46
- end
47
-
48
- def csi_G(col = 1)
49
- cursor.col = col.to_i - 1 # cursor is zero indexed, arg is 1 indexed
50
- end
51
-
52
- def csi_H(row = 1, col = 1)
53
- # cursor is zero indexed, arg is 1 indexed
54
- cursor.row = row.to_i - 1
55
- cursor.col = col.to_i - 1
56
- end
57
- alias csi_f csi_H
58
-
59
- def csi_J(mode = 0)
60
- case mode.to_i
61
- when 0 then screen.clear_forward
62
- when 1 then screen.clear_backward
63
- when 2, 3 then screen.clear
64
- end
65
- end
66
-
67
- def csi_K(mode = 0)
68
- case mode.to_i
69
- when 0 then screen.clear_line_forward
70
- when 1 then screen.clear_line_backward
71
- when 2 then screen.clear_line
72
- end
73
- end
74
-
75
- def csi_m(*args)
76
- end
77
- # rubocop:enable Naming/MethodName
78
-
79
- def slash_b
80
- cursor.left
81
- screen.clear_at_cursor
82
- end
83
-
84
- def slash_n
85
- cursor.down
86
- cursor.col = 0
87
- screen.write('')
88
- end
89
-
90
- def slash_r
91
- cursor.col = 0
92
- end
93
-
94
- def slash_t
95
- cursor.right(8 - (cursor.col % 8))
96
- end
97
-
98
- private
99
-
100
- def cursor
101
- screen.cursor
102
- end
103
- end
104
- end