rcurses 6.3.1 → 6.3.2

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: a56f11dd5e866bf00475278aa8ce3aa2839b214b68cbac65545a72e4a728276b
4
- data.tar.gz: 67c03d594cd01fe4807c88fcbd7951f22a8d5b09def693c23705a392a41ab3af
3
+ metadata.gz: 539d715f0c1f3dfa00a185a2e59e733201ed58f3e75ec9c9c893c5b720a71600
4
+ data.tar.gz: ebcd4c2551bb4efbcab6606b6279eef2e5738a113a03bd3486cdd89b7ef02920
5
5
  SHA512:
6
- metadata.gz: e6a2ae9af2b87338207f6e33814022e751be0a6c78b78cf3105454ca5242b2c716e49a6a6c6a3459229cd0118f1d46200380225e97ade5d9979d674029dc4ea9
7
- data.tar.gz: c27c8713dee2bc09190fef674b27d61fafcffbc674821b6c278bea768353ef9c5ffefafbfd2db00a396737e940557d42ad0491f39d94972d2e9350309c97db8f
6
+ metadata.gz: 673b3e6150f8d2f439a9304512b5f8ad799c2a5f34a2ecf9d826b2161bac569043197dea1d09f62ba5d8cfd1ba6069587487cf8f6d8d11a5302883891bc2fb16
7
+ data.tar.gz: 9c3ccfa42b7de4cf51961ec2d7bdb63bbfcb39bdb2f3b03ee024722cd186602ea8d1c7d3c2126751ec8685e69e046ed1ece3786da6406dab95e9f65d43aae321
@@ -58,9 +58,19 @@ module Rcurses
58
58
  end
59
59
  end
60
60
 
61
- # Simple, fast display_width function
61
+ # Display width cache
62
+ @dw_cache = {}
63
+ DW_CACHE_MAX = 2000
64
+
65
+ def self.clear_dw_cache
66
+ @dw_cache.clear
67
+ end
68
+
69
+ # Simple, fast display_width function (cached)
62
70
  def self.display_width(str)
63
71
  return 0 if str.nil? || str.empty?
72
+ cached = @dw_cache[str]
73
+ return cached if cached
64
74
 
65
75
  width = 0
66
76
  prev_regional = false
@@ -162,6 +172,8 @@ module Rcurses
162
172
  prev_regional = false
163
173
  after_zwj = false
164
174
  end
175
+ @dw_cache.clear if @dw_cache.size >= DW_CACHE_MAX
176
+ @dw_cache[str] = width
165
177
  width
166
178
  end
167
179
 
data/lib/rcurses/pane.rb CHANGED
@@ -1,4 +1,7 @@
1
1
  module Rcurses
2
+ ANSI_RE = /\e\[[0-9;]*m/.freeze
3
+ ANSI_CSI_RE = /\e\[[0-9;]*[A-HJKSTfhlnr]/.freeze
4
+
2
5
  class Pane
3
6
  require 'clipboard' # Ensure the 'clipboard' gem is installed
4
7
  include Cursor
@@ -60,6 +63,11 @@ module Rcurses
60
63
  @history.shift while @history.size > @max_history_size
61
64
  end
62
65
  @text = new_text
66
+ @line_count = nil # Invalidate cache
67
+ end
68
+
69
+ def line_count
70
+ @line_count ||= @text.to_s.count("\n") + 1
63
71
  end
64
72
 
65
73
  def ask(prompt, text)
@@ -113,7 +121,7 @@ module Rcurses
113
121
 
114
122
  def linedown
115
123
  @ix += 1
116
- @ix = @text.split("\n").length if @ix > @text.split("\n").length - 1
124
+ @ix = line_count - 1 if @ix > line_count - 1
117
125
  refresh
118
126
  end
119
127
 
@@ -125,7 +133,8 @@ module Rcurses
125
133
 
126
134
  def pagedown
127
135
  @ix = @ix + @h - 1
128
- @ix = @text.split("\n").length - @h if @ix > @text.split("\n").length - @h
136
+ max = line_count - @h
137
+ @ix = max if @ix > max
129
138
  refresh
130
139
  end
131
140
 
@@ -136,7 +145,7 @@ module Rcurses
136
145
  end
137
146
 
138
147
  def bottom
139
- @ix = @text.split("\n").length - @h
148
+ @ix = line_count - @h
140
149
  refresh
141
150
  end
142
151
 
@@ -334,12 +343,12 @@ module Rcurses
334
343
 
335
344
  # Strip non-SGR ANSI sequences (cursor movement, clear, etc.)
336
345
  # Keep only SGR sequences (ending in 'm') for colors/styles
337
- line_str = line_str.gsub(/\e\[[0-9;]*[A-HJKSTfhlnr]/, '')
346
+ line_str = line_str.gsub(ANSI_CSI_RE, '')
338
347
  # Strip any raw control characters (except tab and ANSI ESC sequences)
339
348
  line_str = line_str.gsub(/[\x00-\x08\x0b-\x1a\x7f]/, '?')
340
349
 
341
350
  # Hard-clip line to pane width to prevent overflow into adjacent panes
342
- visible_w = Rcurses.display_width(line_str.respond_to?(:pure) ? line_str.pure : line_str.gsub(/\e\[[0-9;]*m/, ''))
351
+ visible_w = Rcurses.display_width(line_str.respond_to?(:pure) ? line_str.pure : line_str.gsub(ANSI_RE, ''))
343
352
  if visible_w > @w
344
353
  line_str = line_str.respond_to?(:shorten) ? line_str.shorten(@w) : line_str[0, @w]
345
354
  end
@@ -799,7 +808,7 @@ module Rcurses
799
808
  begin
800
809
  return [""] if line.nil? || w <= 0
801
810
 
802
- ansi_regex = /\e\[[0-9;]*m/
811
+ ansi_regex = ANSI_RE
803
812
  result = []
804
813
  tokens = line.scan(/(\e\[[0-9;]*m|[^\e]+)/).flatten.compact
805
814
  current_line = ''
@@ -92,8 +92,9 @@ class String
92
92
  end
93
93
 
94
94
  # Strip all ANSI SGR sequences
95
+ ANSI_SGR_RE = /\e\[\d+(?:;\d+)*m/.freeze
95
96
  def pure
96
- gsub(/\e\[\d+(?:;\d+)*m/, '')
97
+ gsub(ANSI_SGR_RE, '')
97
98
  end
98
99
 
99
100
  # Remove stray leading/trailing reset if the string has no other styling
@@ -162,7 +163,7 @@ class String
162
163
  def safe_gsub(pattern, replacement = nil, &block)
163
164
  # Store all ANSI sequences and replace with placeholders
164
165
  ansi_sequences = []
165
- placeholder_text = self.gsub(/\e\[[0-9;]*m/) do |match|
166
+ placeholder_text = self.gsub(Rcurses::ANSI_RE) do |match|
166
167
  ansi_sequences << match
167
168
  "⟨ANSI#{ansi_sequences.length - 1}⟩"
168
169
  end
@@ -190,7 +191,7 @@ class String
190
191
 
191
192
  # Check if string contains ANSI codes
192
193
  def has_ansi?
193
- !!(self =~ /\e\[[0-9;]*m/)
194
+ !!(self =~ Rcurses::ANSI_RE)
194
195
  end
195
196
 
196
197
  # Get the visible length (without ANSI codes)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rcurses
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.3.1
4
+ version: 6.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geir Isene
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-03-24 00:00:00.000000000 Z
11
+ date: 2026-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clipboard