Vibe Coding: textfx 若干 issue 更新
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-02-16 19:36:24 +08:00
parent 58ff8f02da
commit d4cde42bdc
5 changed files with 343 additions and 75 deletions

View File

@ -23,7 +23,7 @@ class TextHandleResult:
class TextHandler(ABC):
name: str = ''
name: str = ""
keywords: list[str] = []
@abstractmethod
@ -37,12 +37,16 @@ class TextHandler(ABC):
class TextHandlerSync(TextHandler):
@abstractmethod
def handle_sync(self, env: TextHandlerEnvironment, istream: str | None, args: list[str]) -> TextHandleResult:
...
def handle_sync(
self, env: TextHandlerEnvironment, istream: str | None, args: list[str]
) -> TextHandleResult: ...
async def handle(self, env: TextHandlerEnvironment, istream: str | None, args: list[str]) -> TextHandleResult:
async def handle(
self, env: TextHandlerEnvironment, istream: str | None, args: list[str]
) -> TextHandleResult:
def _hs():
return self.handle_sync(env, istream, args)
return await asyncio.to_thread(_hs)
@ -99,6 +103,7 @@ class PipelineRunner:
current_string = ""
current_string_raw = ""
status_in_string_pair = ""
has_token = False # 是否正在构建一个 token区分空字符串和无 token
# 重定向解析状态
is_parsing_redirect_filename = False
@ -111,8 +116,9 @@ class PipelineRunner:
current_string, \
current_string_raw, \
is_parsing_redirect_filename, \
current_redirect_target
if not current_string:
current_redirect_target, \
has_token
if not has_token:
return
if is_parsing_redirect_filename:
@ -123,6 +129,7 @@ class PipelineRunner:
current_string = ""
current_string_raw = ""
has_token = False
# 辅助函数:将当前指令 flush 到当前组
def _flush_command() -> str | None:
@ -176,6 +183,7 @@ class PipelineRunner:
status_in_string_pair = c
status = PipelineParseStatus.in_string
current_string_raw = ""
has_token = True
elif c == "|":
_flush_token()
@ -206,6 +214,7 @@ class PipelineRunner:
else:
current_string += c
has_token = True
case PipelineParseStatus.in_string:
current_string_raw += c
@ -217,7 +226,18 @@ class PipelineRunner:
current_string += c
case PipelineParseStatus.in_string_to_escape:
current_string += c
escape_map = {
"n": "\n",
"r": "\r",
"t": "\t",
"0": "\0",
"a": "\a",
"b": "\b",
"f": "\f",
"v": "\v",
"\\": "\\",
}
current_string += escape_map.get(c, c)
status = PipelineParseStatus.in_string
case PipelineParseStatus.off_string:
@ -265,24 +285,19 @@ class PipelineRunner:
pipeline: Pipeline,
istream: str | None,
env: TextHandlerEnvironment | None = None,
) -> TextHandleResult:
) -> list[TextHandleResult]:
if env is None:
# 默认环境
env = TextHandlerEnvironment(is_trusted=False, buffers={})
final_result = TextHandleResult(code=0, ostream=istream)
results: list[TextHandleResult] = []
# 遍历执行指令组 (分号分隔)
# 遍历执行指令组 (分号分隔),每个组独立产生输出
for group in pipeline.command_groups:
# 每个组开始时,使用原始输入(或者根据需求设为 None这里假设每个组独立处理 istream
# 通常分号分隔的命令组,第一条命令如果没有 pipe 输入,它接收的 istream 取决于整体输入
current_stream = istream
group_result = TextHandleResult(code=0, ostream=None)
# 遍历组内指令 (管道分隔)
for cmd in group:
if final_result.code != 0:
break
try:
logger.debug(
f"Executing: {cmd.handler.name} args={cmd.args} redirect={cmd.redirect_target}"
@ -290,8 +305,9 @@ class PipelineRunner:
result = await cmd.handler.handle(env, current_stream, cmd.args)
if result.code != 0:
final_result = result
break
# 组内出错,整条流水线中止
results.append(result)
return results
# 处理重定向逻辑
if cmd.redirect_target:
@ -304,29 +320,27 @@ class PipelineRunner:
else:
env.buffers[target_buffer] = content_to_write
# 重定向后,标准输出通常被消耗,后续管道接收到的流为空 (或 None)
# 除非实现 tee 逻辑,否则视为流已终止
current_stream = None
# 更新最终结果,但 ostream 设为 None 因为被重定向了
final_result = TextHandleResult(
group_result = TextHandleResult(
code=0, ostream=None, attachment=result.attachment
)
else:
current_stream = result.ostream
final_result = result
group_result = result
except Exception as e:
logger.error(f"Pipeline execution failed at {cmd.handler.name}")
logger.exception(e)
return TextHandleResult(code=-1, ostream="处理流水线时出现 python 错误")
results.append(
TextHandleResult(
code=-1, ostream="处理流水线时出现 python 错误"
)
)
return results
# 一个组执行完final_result保留该组最后的状态。
# 如果还有下一个组final_result.code 如果是 0 则继续执行下一个组
if final_result.code != 0:
break
results.append(group_result)
return final_result
return results
def register_text_handlers(*handlers: TextHandler):