good_luck_wizard 0.0.3 → 0.0.4

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: c0cb37ba935956a080d7e4f02a6f771d50c78396d9929d5424d1f9427f354bc1
4
- data.tar.gz: 185370ffabbe5b7688304cb97cf8fa1a385e49e9461cff77e8f185763bec3434
3
+ metadata.gz: 4542c554b53395dec06ab3026510aa4ad8b24511077f0820e607daa8a48eeb57
4
+ data.tar.gz: 6991409bd222f25a008b86716cda64f1cb06928637882ade5676e5114a126c5c
5
5
  SHA512:
6
- metadata.gz: f03c3bdc66579466bad239ff5f04faaa4cfef2ea547364e083955ee8a43e371d4b33aa3652882088a6906193269f20b8136d496fb8454f11ab94231f2df60551
7
- data.tar.gz: 1716b9749d7ec53582ab84234cdc9927ac49ec8f8a12b1d741fed7a3f436a89a392b74d5c3bd22b5d0bdd5233d74dafb817532ac4849b33a57c9172102651832
6
+ metadata.gz: acd95d8a41e16661a57ec519052d91ff93747478ba29d8b4882e1e1c7207297427df4af973f55bed324af70758aca83a078cc81f27e16939c27d334ff8212e2f
7
+ data.tar.gz: 5f56f58dc3a2074ab355f2694ae40356f10d5623b1f8186790c75cfbba5dd78e075017bd55d77b37bb324e027b67d624d703041d9904aee952ea6442cb4da0b1
data/Gemfile CHANGED
@@ -8,3 +8,5 @@ gemspec
8
8
  gem "rake", "~> 13.2"
9
9
  gem "rspec", "~> 3.4"
10
10
  gem "standard", "~> 1.45"
11
+
12
+ gem "debug"
data/README.md CHANGED
@@ -1,26 +1,20 @@
1
- **Good Luck, Wizard**. You're going to need it. Especially because this is an
2
- _extremely_ unfinished game. It's hard to even call it a game at this point. You
3
- should come back later when there's something worth playing.
1
+ **good luck, wizard**. you're going to need it. not least of all because this is
2
+ an _extremely_ unfinished game. not really a game at all, yet. come back later.
4
3
 
5
- **If you absolutely must try it, you can install it** with `gem install
6
- good_luck_wizard` and run it with `glw`. This assumes you have a working Ruby
4
+ if you absolutely must try it, you can install it with `gem install
5
+ good_luck_wizard` and run it with `glw`. this assumes you have a working Ruby
7
6
  environment and a new enough version of Ruby.
8
7
 
9
- **This project is not seeking contributions,** but bug reports are accepted [on
8
+ this project is not seeking contributions, but bug reports are accepted [on
10
9
  GitHub](https://github.com/jarednorman/good_luck_wizard).
11
10
 
12
- **This project is intended to be a safe, welcoming space for collaboration.**
13
- Everyone interacting in the _Good Luck, Wizard_ project’s codebases, issue
14
- trackers, chat rooms and mailing lists is expected to follow the [code of
11
+ this project is intended to be a safe, welcoming space for collaboration. yes,
12
+ even though i don't want you to contribute, i will still ensure you aren't
13
+ descriminated against if you try. everyone interacting in the _good luck,
14
+ wizard_ project’s codebases, issue trackers, chat rooms and mailing lists is
15
+ expected to follow the [code of
15
16
  conduct](https://github.com/jarednorman/good_luck_wizard/blob/master/CODE_OF_CONDUCT.md).
16
17
 
17
- ---
18
-
19
- **To run thep roject locally,** checck out the repo and run `bin/setup` to
20
- install dependencies. The tests are run with `bundle exec rspec`. You can also
21
- run `bin/console` for an interactive prompt that will allow you to experiment.
22
-
23
- To release a new version, update the version number in `version.rb`, and then
24
- run `bundle exec rake release`, which will create a git tag for the version,
25
- push git commits and tags, and push the `.gem` file to
26
- [rubygems.org](https://rubygems.org).
18
+ to run the project locally: check out the repo and run `bin/setup` to install
19
+ dependencies. the tests are run with `bundle exec rspec`. you can also run
20
+ `bin/console` for an interactive prompt that will allow you to experiment.
data/Rakefile CHANGED
@@ -7,4 +7,4 @@ Rake::TestTask.new(:test) do |t|
7
7
  t.test_files = FileList["test/**/*_test.rb"]
8
8
  end
9
9
 
10
- task :default => :test
10
+ task default: :test
data/bin/release ADDED
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "date"
5
+ require "fileutils"
6
+
7
+ # Parse version argument
8
+ if ARGV.empty?
9
+ puts "Usage: bin/release VERSION"
10
+ puts "Example: bin/release 1.2.3"
11
+ exit 1
12
+ end
13
+
14
+ version = ARGV[0]
15
+ unless version.match?(/^\d+\.\d+\.\d+$/)
16
+ puts "Error: Version must be in format X.Y.Z (e.g., 1.2.3)"
17
+ exit 1
18
+ end
19
+
20
+ puts "Releasing version #{version}..."
21
+
22
+ # 1. Update lib/glw/version.rb
23
+ version_file = "lib/glw/version.rb"
24
+ version_content = File.read(version_file)
25
+ updated_version_content = version_content.gsub(
26
+ /VERSION = "[^"]+"/,
27
+ %(VERSION = "#{version}")
28
+ )
29
+ File.write(version_file, updated_version_content)
30
+ puts "✓ Updated #{version_file}"
31
+
32
+ # 4. Commit changes
33
+ commit_message = "v#{version}"
34
+ system("jj", "commit", "-m", commit_message) || exit(1)
35
+ puts "✓ Committed changes with message '#{commit_message}'"
36
+
37
+ # 5. Move main branch to the change we just made
38
+ system("jj", "bookmark", "set", "main", "-r", "@-") || exit(1)
39
+ puts "✓ Moved main branch to release commit"
40
+
41
+ # 6. Tag the version
42
+ tag_name = "v#{version}"
43
+ tag_message = "Version #{version}"
44
+ system("git", "tag", "-m", tag_message, tag_name) || exit(1)
45
+ puts "✓ Created tag #{tag_name}"
46
+
47
+ # 7. Push changes and tags
48
+ system("jj", "git", "push", "-b", "main") || exit(1)
49
+ puts "✓ Pushed main branch"
50
+
51
+ system("git", "push", "--tags") || exit(1)
52
+ puts "✓ Pushed tags"
53
+
54
+ # 8. Build and push gem
55
+ gem_file = "good_luck_wizard-#{version}.gem"
56
+ system("gem", "build", "good_luck_wizard.gemspec") || exit(1)
57
+ puts "✓ Built gem"
58
+
59
+ system("gem", "push", gem_file) || exit(1)
60
+ puts "✓ Pushed gem"
61
+
62
+ system("rm", gem_file)
63
+ puts "✓ Cleaned up gem file"
64
+
65
+ puts "\n🎉 Successfully released version #{version}!"
data/exe/glw CHANGED
@@ -1,4 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'glw'
3
+ if ENV["DEBUG"] == "true"
4
+ # This avoids terminal corruption unless something has actually gone wrong.
5
+ ENV["RUBY_DEBUG_LOG_LEVEL"] = "ERROR"
6
+
7
+ require "debug/open_nonstop"
8
+ end
9
+
10
+ require "glw"
4
11
  GLW.start!
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.required_ruby_version = ">= 3.4.0"
26
26
 
27
- spec.add_dependency "curses", "~> 1.4.0"
28
27
  spec.add_dependency "zeitwerk", "~> 2.4"
28
+ spec.add_dependency "concurrent-ruby"
29
+ spec.add_dependency "concurrent-ruby-edge", "~> 0.7"
29
30
  end
@@ -0,0 +1,15 @@
1
+ module GLW
2
+ BufferState = Data.define(:width, :height, :cells) do
3
+ def self.blank(height:, width:)
4
+ new(
5
+ width,
6
+ height,
7
+ Array.new(height * width) { ScreenCell.blank }
8
+ )
9
+ end
10
+
11
+ def [](x, y)
12
+ cells[y * width + x]
13
+ end
14
+ end
15
+ end
data/lib/glw/input.rb ADDED
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GLW
4
+ module Input
5
+ class << self
6
+ ESCAPE_TIMEOUT = 0.02 # 20ms
7
+
8
+ BYTES = {
9
+ "\t" => :k_tab,
10
+ "\r" => :k_enter,
11
+ "\n" => :k_enter,
12
+ "\x7F" => :k_backspace,
13
+ "\b" => :k_backspace,
14
+ " " => :k_space,
15
+ "\x03" => :k_ctrl_c,
16
+ "[" => :k_left_bracket,
17
+ "]" => :k_right_bracket,
18
+ ";" => :k_semicolon,
19
+ "'" => :k_single_quote,
20
+ "," => :k_comma,
21
+ "." => :k_period
22
+ }.tap do |h|
23
+ ("a".."z").each { |c| h[c] = :"k_#{c}" }
24
+ ("A".."Z").each { |c| h[c] = :"k_#{c}" }
25
+ ("0".."9").each { |c| h[c] = :"k_#{c}" }
26
+ end
27
+
28
+ def pop
29
+ @queue.pop
30
+ end
31
+
32
+ def start!
33
+ return if @queue
34
+
35
+ @queue = Thread::Queue.new
36
+
37
+ Thread.new do
38
+ loop do
39
+ byte = read_byte
40
+
41
+ if byte == "\e"
42
+ handle_escape byte
43
+ else
44
+ handle_byte byte
45
+ end
46
+ rescue EOFError
47
+ break
48
+ end
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def handle_escape(first_byte)
55
+ second_byte = read_byte(timeout: true)
56
+
57
+ if second_byte.nil?
58
+ @queue << :k_escape
59
+ nil
60
+ elsif second_byte == "["
61
+ third_byte = read_byte(timeout: true)
62
+
63
+ case third_byte
64
+ when "A"
65
+ @queue << :k_up
66
+ when "B"
67
+ @queue << :k_down
68
+ when "C"
69
+ @queue << :k_right
70
+ when "D"
71
+ @queue << :k_left
72
+ else
73
+ @queue << :k_escape
74
+ handle_byte second_byte
75
+ handle_byte third_byte if third_byte
76
+ end
77
+ else
78
+ @queue << :k_escape
79
+ handle_byte second_byte
80
+ end
81
+ end
82
+
83
+ def handle_byte(byte)
84
+ return unless BYTES.key?(byte)
85
+
86
+ @queue << BYTES[byte]
87
+ end
88
+
89
+ def read_byte(timeout: false)
90
+ return if timeout && !IO.select([STDIN], nil, nil, 0.02)
91
+
92
+ STDIN.readpartial(1)
93
+ end
94
+ end
95
+ end
96
+ end
data/lib/glw/screen.rb ADDED
@@ -0,0 +1,103 @@
1
+ module GLW
2
+ module Screen
3
+ class << self
4
+ UpdateBlock = Data.define(:start_index, :cells) do
5
+ def self.make(start_index) = new(start_index, [])
6
+
7
+ def to_s(current_fg: nil, current_bg: nil)
8
+ output = ""
9
+ fg = current_fg
10
+ bg = current_bg
11
+
12
+ cells.each do |cell|
13
+ if cell.fg_color != fg
14
+ output << Terminal.set_fg(cell.fg_color)
15
+ fg = cell.fg_color
16
+ end
17
+
18
+ if cell.bg_color != bg
19
+ output << Terminal.set_bg(cell.bg_color)
20
+ bg = cell.bg_color
21
+ end
22
+
23
+ output << cell.char
24
+ end
25
+
26
+ [output, fg, bg]
27
+ end
28
+ end
29
+
30
+ def start!
31
+ @render_queue = Thread::Queue.new
32
+
33
+ @render_queue.push BufferState.blank(
34
+ height: IO.console.winsize[0],
35
+ width: IO.console.winsize[1]
36
+ )
37
+
38
+ Thread.new do
39
+ STDOUT.print Terminal.hide_cursor
40
+
41
+ last_state = nil
42
+
43
+ loop do
44
+ state = @render_queue.pop
45
+
46
+ # Throw away stale states until we have the newest one.
47
+ state = @render_queue.pop until @render_queue.empty?
48
+
49
+ render(last_state, state)
50
+ last_state = state
51
+ end
52
+ end
53
+ end
54
+
55
+ def push_state(state)
56
+ @render_queue.push(state)
57
+ end
58
+
59
+ private
60
+
61
+ def render(last_state, state)
62
+ updates = []
63
+ current_block = nil
64
+
65
+ state.cells.each_with_index do |cell, index|
66
+ next if last_state && cell == last_state.cells[index]
67
+
68
+ if current_block && current_block.start_index + current_block.cells.length == index
69
+ current_block.cells << cell
70
+ else
71
+ updates << current_block if current_block
72
+
73
+ current_block = UpdateBlock.new(index, [cell])
74
+ end
75
+ end
76
+
77
+ updates << current_block if current_block
78
+
79
+ current_fg = nil
80
+ current_bg = nil
81
+
82
+ STDOUT.print(
83
+ updates.flat_map do |block|
84
+ y = block.start_index / state.width
85
+ x = block.start_index % state.width
86
+
87
+ block_output, current_fg, current_bg = block.to_s(
88
+ current_fg:,
89
+ current_bg:
90
+ )
91
+
92
+ [
93
+ Terminal.move_to(x, y),
94
+ block_output
95
+ ]
96
+ end.join
97
+ )
98
+
99
+ STDOUT.flush
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,7 @@
1
+ module GLW
2
+ ScreenCell = Data.define(:char, :fg_color, :bg_color) do
3
+ def self.blank
4
+ @blank ||= new(" ", :black, :black)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,31 @@
1
+ module GLW
2
+ module Terminal
3
+ class << self
4
+ PALETTE = {
5
+ black: [0, 0, 0],
6
+ white: [255, 255, 255]
7
+ }.transform_values do |(r, g, b)|
8
+ [
9
+ "\e[38;2;#{r};#{g};#{b}m",
10
+ "\e[48;2;#{r};#{g};#{b}m"
11
+ ]
12
+ end.freeze
13
+
14
+ def move_to(x, y)
15
+ "\e[#{y + 1};#{x + 1}H"
16
+ end
17
+
18
+ def set_fg(color)
19
+ PALETTE.fetch(color)[0]
20
+ end
21
+
22
+ def set_bg(color)
23
+ PALETTE.fetch(color)[1]
24
+ end
25
+
26
+ def hide_cursor
27
+ "\e[?25l"
28
+ end
29
+ end
30
+ end
31
+ end
data/lib/glw/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module GLW
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
data/lib/glw.rb CHANGED
@@ -1,33 +1,31 @@
1
- require 'curses'
1
+ require "io/console"
2
+ require "concurrent/actor"
3
+
2
4
  require "zeitwerk"
3
5
 
4
- require "glw/version"
6
+ Zeitwerk::Loader.for_gem.tap do |loader|
7
+ loader.inflector.inflect(
8
+ "glw" => "GLW"
9
+ )
10
+
11
+ loader.setup
12
+ end
5
13
 
6
14
  module GLW
7
15
  class << self
8
16
  def start!
9
- initialize_zeitwerk
10
-
11
- GLW::Term.with_term do |t|
12
- g = Game.new(term: t)
17
+ IO.console.raw do
18
+ Screen.start!
19
+ Input.start!
13
20
 
14
21
  loop do
15
- g.render
16
- break if g.send_key(t.getch) == :quit
17
- end
18
- end
19
- end
20
-
21
- def initialize_zeitwerk
22
- return if @zeitwerk_enabled
22
+ content = Input.pop
23
23
 
24
- Zeitwerk::Loader.new.tap do |loader|
25
- loader.inflector.inflect("glw" => "GLW")
26
- loader.push_dir(__dir__)
27
- loader.setup
24
+ exit(0) if content == :k_escape || content == :k_ctrl_c
25
+ end
28
26
  end
29
-
30
- @zeitwerk_enabled = true
27
+ rescue
28
+ raise
31
29
  end
32
30
  end
33
31
  end
data/test_input.rb ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "lib/glw"
5
+
6
+ puts "Input Test - Press keys to see symbols (press 'q' or Ctrl-C to quit)"
7
+ puts "Try: letters, numbers, arrows, ESC, space, tab, enter, backspace, Ctrl-C"
8
+ puts "-" * 60
9
+
10
+ IO.console.raw do
11
+ GLW::Input.start!
12
+
13
+ loop do
14
+ key = GLW::Input.pop
15
+ puts "Received: #{key.inspect}"
16
+
17
+ break if key == :k_q || key == :k_ctrl_c
18
+ end
19
+ end
20
+
21
+ puts "\nExiting..."
metadata CHANGED
@@ -1,42 +1,56 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: good_luck_wizard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jared Norman
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-03-09 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
- name: curses
13
+ name: zeitwerk
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: 1.4.0
18
+ version: '2.4'
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: 1.4.0
25
+ version: '2.4'
26
26
  - !ruby/object:Gem::Dependency
27
- name: zeitwerk
27
+ name: concurrent-ruby
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: concurrent-ruby-edge
28
42
  requirement: !ruby/object:Gem::Requirement
29
43
  requirements:
30
44
  - - "~>"
31
45
  - !ruby/object:Gem::Version
32
- version: '2.4'
46
+ version: '0.7'
33
47
  type: :runtime
34
48
  prerelease: false
35
49
  version_requirements: !ruby/object:Gem::Requirement
36
50
  requirements:
37
51
  - - "~>"
38
52
  - !ruby/object:Gem::Version
39
- version: '2.4'
53
+ version: '0.7'
40
54
  description: An unfinished terminal-based roguelike game
41
55
  email:
42
56
  - jared@super.gd
@@ -53,16 +67,19 @@ files:
53
67
  - README.md
54
68
  - Rakefile
55
69
  - bin/console
70
+ - bin/release
56
71
  - bin/setup
57
72
  - exe/glw
58
73
  - good_luck_wizard.gemspec
59
74
  - lib/glw.rb
60
- - lib/glw/game.rb
61
- - lib/glw/map.rb
75
+ - lib/glw/buffer_state.rb
76
+ - lib/glw/input.rb
62
77
  - lib/glw/random.rb
63
- - lib/glw/term.rb
64
- - lib/glw/term_colors.rb
78
+ - lib/glw/screen.rb
79
+ - lib/glw/screen_cell.rb
80
+ - lib/glw/terminal.rb
65
81
  - lib/glw/version.rb
82
+ - test_input.rb
66
83
  homepage: http://github.com/jarednorman/good_luck_wizard
67
84
  licenses: []
68
85
  metadata: {}
@@ -80,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
97
  - !ruby/object:Gem::Version
81
98
  version: '0'
82
99
  requirements: []
83
- rubygems_version: 3.6.2
100
+ rubygems_version: 4.0.2
84
101
  specification_version: 4
85
102
  summary: An unfinished terminal-based roguelike game
86
103
  test_files: []
data/lib/glw/game.rb DELETED
@@ -1,31 +0,0 @@
1
- module GLW
2
- class Game
3
- def initialize(term:)
4
- @map = Map.new
5
- @term = term
6
- end
7
-
8
- def send_key(key)
9
- case key
10
- when "q"
11
- :quit
12
- when "h"
13
- @map.send_event :left
14
- when "l"
15
- @map.send_event :right
16
- when "k"
17
- @map.send_event :up
18
- when "j"
19
- @map.send_event :down
20
- end
21
- end
22
-
23
- def render
24
- map.render(term, width: term.width - 60, height: term.height)
25
- end
26
-
27
- private
28
-
29
- attr_reader :term, :map
30
- end
31
- end
data/lib/glw/map.rb DELETED
@@ -1,71 +0,0 @@
1
- module GLW
2
- class Map
3
- MAP = <<~TXT
4
- ############
5
- #..........# ##########
6
- #..........############....#...#
7
- #..............................#
8
- #.......g..############....#...#
9
- #..........# #....#...#
10
- ############ ##########
11
- TXT
12
-
13
- def initialize
14
- @player_x = 3
15
- @player_y = 3
16
-
17
- @map = Hash.new(" ")
18
- MAP.lines.each_with_index do |line, y|
19
- line.chars.each_with_index do |c, x|
20
- @map[[x, y]] = c
21
- end
22
- end
23
-
24
- @offset_x = 1
25
- @offset_y = 1
26
- end
27
-
28
- def send_event(e)
29
- case e
30
- when :left
31
- @player_x -= 1 if valid_player_position?(@player_x - 1, @player_y)
32
- when :right
33
- @player_x += 1 if valid_player_position?(@player_x + 1, @player_y)
34
- when :up
35
- @player_y -= 1 if valid_player_position?(@player_x, @player_y - 1)
36
- when :down
37
- @player_y += 1 if valid_player_position?(@player_x, @player_y + 1)
38
- end
39
- end
40
-
41
- def render(term, width:, height:)
42
- (0..width - 1).each do |x|
43
- (0..height - 1).each do |y|
44
-
45
- if [@player_x + @offset_x, @player_y + @offset_y] == [x, y]
46
- term.set(
47
- x: x,
48
- y: y,
49
- c: "@",
50
- fg: 220
51
- )
52
- else
53
- term.set(
54
- x: x,
55
- y: y,
56
- c: @map[[x - @offset_x, y - @offset_y]]
57
- )
58
- end
59
- end
60
- end
61
-
62
- term.refresh
63
- end
64
-
65
- private
66
-
67
- def valid_player_position?(x, y)
68
- @map[[x, y]] == "."
69
- end
70
- end
71
- end
data/lib/glw/term.rb DELETED
@@ -1,72 +0,0 @@
1
- module GLW
2
- # This class is responsible for handling all interactions with the terminal
3
- # so that this thing can be half-ways frontend independent, though I have no
4
- # intention of ever switching frontends.
5
- class Term
6
- DEFAULT_FG = 255
7
- DEFAULT_BG = 16
8
-
9
- Cell = Struct.new(:c, :fg, :bg)
10
-
11
- DEFAULT_CELL = Cell.new(" ", DEFAULT_FG, DEFAULT_BG)
12
-
13
- class << self
14
- def with_term
15
- Curses.init_screen
16
- Curses.start_color
17
- Curses.curs_set(0)
18
- Curses.noecho
19
-
20
- Curses.assume_default_colors(DEFAULT_FG, DEFAULT_BG)
21
-
22
- yield new(Curses::Window.new(0, 0, 0, 0))
23
- ensure
24
- Curses.close_screen
25
- end
26
- end
27
-
28
- def initialize(window)
29
- @window = window
30
- @tiles = Hash.new { DEFAULT_CELL }
31
- @next_tiles = {}
32
- @colors = TermColors.new
33
- end
34
-
35
- def set(x:, y:, c:, fg: DEFAULT_FG, bg: DEFAULT_BG)
36
- cell = Cell.new(c, fg, bg)
37
-
38
- @next_tiles[[x, y]] = cell unless @tiles[[x, y]] == cell
39
- end
40
-
41
- def width
42
- Curses.cols
43
- end
44
-
45
- def height
46
- Curses.lines
47
- end
48
-
49
- def getch
50
- window.getch
51
- end
52
-
53
- def refresh
54
- @next_tiles.each do |coords, cell|
55
- x, y = *coords
56
- window.setpos(y, x)
57
-
58
- window.attron(colors[cell.fg, cell.bg]) do
59
- window << cell.c
60
- end
61
- end
62
-
63
- @tiles = @tiles.merge(@next_tiles)
64
-
65
- window.refresh
66
- end
67
-
68
- private
69
-
70
- attr_reader :window, :colors
71
- end
72
- end
@@ -1,22 +0,0 @@
1
- module GLW
2
- class TermColors
3
- def initialize(curses = Curses)
4
- index = 1
5
-
6
- @colors = Hash.new do |hash, key|
7
- fg, bg = *key
8
-
9
- curses.init_pair(index, fg, bg)
10
- hash[key] = curses.color_pair(index)
11
-
12
- index += 1
13
-
14
- hash[key]
15
- end
16
- end
17
-
18
- def [](fg, bg)
19
- @colors[[fg, bg]]
20
- end
21
- end
22
- end