expect-pty 0.8.0 → 0.8.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/lib/expect/interaction.rb +15 -10
- data/lib/expect/logging.rb +2 -1
- data/lib/expect/matcher.rb +8 -4
- data/lib/expect/redactor.rb +2 -0
- data/lib/expect/session.rb +2 -2
- data/lib/expect/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f85e305b108edbac5d96859d034af4221948535a6f160296072eb1c8189c8cfc
|
|
4
|
+
data.tar.gz: 83fa7073bac3d7b17ad16f8fb6bf0bbf34d14379378d9813585b64be5ffd2e52
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3b4cd1a931adbe60f6d12be3fa49adc43ba9605bbd9c7730661ed435f49b68d3cbaac64a2b3a753134a1350a1edaeaa8c363a27eba837af2ac38663dc336d4ac
|
|
7
|
+
data.tar.gz: 74de2bb39b847334e691ea6d6e47f0bce3417ac6755c1aa91ccdc85cf5b00c21924df9a60a2ad09b525038200d6c4877bad2af826fdff5f8998093b5b7ee457f
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.8.1 - 2026-10-11
|
|
6
|
+
|
|
7
|
+
- 修复自动应答已在缓冲开头确定获胜模式,却被后续无关正则的编码错误阻断的问题,保留未消费尾部。
|
|
8
|
+
- 修复 EOF 时 transcript 尾部交付失败跳过接收诊断收尾的问题,两个日志通道均尝试冲刷并保留首个常规异常。
|
|
9
|
+
- 降低大量规则继续匹配、转义扫描和单对象日志补记的开销,并让脱敏流结束后的可见日志恢复普通过滤路径。
|
|
10
|
+
|
|
5
11
|
## 0.8.0 - 2026-10-11
|
|
6
12
|
|
|
7
13
|
- 新增可复用的自动应答规则,支持重复确认、分页按键、动态回复和次数上限,按输入顺序处理提示且不延长等待期限,并提供批量脚本示例。
|
data/lib/expect/interaction.rb
CHANGED
|
@@ -137,25 +137,30 @@ module Expect
|
|
|
137
137
|
def self.scan_sequences(buffer, sequences, history, final:)
|
|
138
138
|
text = nil
|
|
139
139
|
utf8_regexp = false
|
|
140
|
-
|
|
140
|
+
earliest = nil
|
|
141
|
+
# 只保存最早候选,同位置不替换先注册者;仍扫描全部正则以校验零宽规则并收集编码状态。
|
|
142
|
+
sequences.each do |key, handler|
|
|
141
143
|
if key.is_a?(Regexp)
|
|
142
144
|
# 仅在本轮扫描复用组合文本;回调可能更换规则或消费缓冲,下一轮必须重新构造。
|
|
143
145
|
text ||= history + buffer
|
|
144
146
|
utf8_regexp ||= key.fixed_encoding? && key.encoding == Encoding::UTF_8
|
|
145
147
|
position = Pattern.new(value: key).locate(text, final:, captures: false)
|
|
146
|
-
|
|
147
|
-
offset, length, = position
|
|
148
|
-
raise ArgumentError, "escape regexp must consume at least one byte" if length.zero?
|
|
148
|
+
next unless position
|
|
149
149
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
offset, length, = position
|
|
151
|
+
raise ArgumentError, "escape regexp must consume at least one byte" if length.zero?
|
|
152
|
+
|
|
153
|
+
# 历史前缀已实时转发,不能撤回;负偏移表示本次只需消费转义尚未转发的部分。
|
|
154
|
+
offset -= history.bytesize
|
|
153
155
|
else
|
|
154
|
-
|
|
155
|
-
|
|
156
|
+
offset = buffer.index(key)
|
|
157
|
+
next unless offset
|
|
158
|
+
|
|
159
|
+
length = key.bytesize
|
|
156
160
|
end
|
|
161
|
+
earliest = [offset, length, handler] if !earliest || offset < earliest.first
|
|
157
162
|
end
|
|
158
|
-
[
|
|
163
|
+
[earliest, !text.nil?, utf8_regexp]
|
|
159
164
|
end
|
|
160
165
|
|
|
161
166
|
# 普通转发和超时排出的字面前缀都属于正则历史,跨次转接时必须接续同一字节流。
|
data/lib/expect/logging.rb
CHANGED
|
@@ -53,7 +53,8 @@ module Expect
|
|
|
53
53
|
def write_transcript(*objects)
|
|
54
54
|
return unless transcript
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
# 单对象沿用 Session#write 的转换路径,省去数组与 join;转换后仍重新取得目标。
|
|
57
|
+
data = objects.size == 1 ? objects.first.to_s.b : objects.map { |object| object.to_s.b }.join
|
|
57
58
|
# to_s 可切换或禁用记录目标;整条记录与其过滤尾部必须属于转换完成后的同一目标。
|
|
58
59
|
target = transcript
|
|
59
60
|
return unless target
|
data/lib/expect/matcher.rb
CHANGED
|
@@ -94,7 +94,7 @@ module Expect
|
|
|
94
94
|
end
|
|
95
95
|
patterns.each do |pattern|
|
|
96
96
|
return nil if hard_expired?
|
|
97
|
-
next if stalled && stalled[:patterns].
|
|
97
|
+
next if stalled && stalled[:patterns].key?(pattern)
|
|
98
98
|
|
|
99
99
|
position = if pattern.value.is_a?(String)
|
|
100
100
|
locate_literal(session, pattern, buffer)
|
|
@@ -105,7 +105,8 @@ module Expect
|
|
|
105
105
|
return nil if hard_expired?
|
|
106
106
|
next unless position
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
# 字节 0 已是最早位置,同位置仍由先声明者胜出;不再执行无法胜出的规则。
|
|
109
|
+
return [session, pattern, position] if !@match_by_position || position.first.zero?
|
|
109
110
|
|
|
110
111
|
earliest = [session, pattern, position] if !earliest || position.first < earliest.last.first
|
|
111
112
|
end
|
|
@@ -153,8 +154,11 @@ module Expect
|
|
|
153
154
|
|
|
154
155
|
# 同值赋回仍须防止空转;嵌套读取到的新字节即使内容相同,也能恢复匹配。
|
|
155
156
|
if session.received_bytes == received_bytes && session.scan_buffer == previous_buffer
|
|
156
|
-
|
|
157
|
-
stalled[
|
|
157
|
+
# 声明模式各有独立身份;恒定成本查询,避免重复继续时遍历不断增长的停滞数组。
|
|
158
|
+
stalled = (@stalled_matches[session] ||= {
|
|
159
|
+
buffer: previous_buffer, received_bytes:, patterns: {}.compare_by_identity
|
|
160
|
+
})
|
|
161
|
+
stalled[:patterns][pattern] = true
|
|
158
162
|
end
|
|
159
163
|
@deadline = next_deadline if CONTINUE.equal?(action)
|
|
160
164
|
# 总期限到达时回主循环先派发已知 EOF;仅相对期限延续原有立即超时语义。
|
data/lib/expect/redactor.rb
CHANGED
data/lib/expect/session.rb
CHANGED
|
@@ -576,8 +576,8 @@ module Expect
|
|
|
576
576
|
# 只结束读取方向并冲刷接收记录;EOF 不代表子进程已经退出或写端已经关闭。
|
|
577
577
|
def mark_eof
|
|
578
578
|
@eof = true
|
|
579
|
-
|
|
580
|
-
flush_diagnostics(:received)
|
|
579
|
+
# EOF 只登记一次;任一日志尾部失败也必须尝试另一通道,保持首个常规异常。
|
|
580
|
+
Cleanup.always(-> { flush_diagnostics(:received) }) { flush_transcript }
|
|
581
581
|
nil
|
|
582
582
|
end
|
|
583
583
|
|
data/lib/expect/version.rb
CHANGED