@@ -2669,6 +2669,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
26692669 return m , nil
26702670 }
26712671
2672+ beforeVal := m .input .Value ()
26722673 var inputCmd tea.Cmd
26732674 m .input , inputCmd = m .input .Update (msg )
26742675 cmds = append (cmds , inputCmd )
@@ -2680,11 +2681,40 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
26802681 // 下一拍 600ms tick 仍按既有节奏 toggle,不 reset 时钟。
26812682 if _ , ok := msg .(tea.KeyPressMsg ); ok {
26822683 m .cursorBlinkOff = false
2684+ // issue #113:行中插入宽字符(把右边内容向右挤)会触发 ultraviolet 行 diff 双写,
2685+ // 在不能自愈的终端(Windows conhost/PowerShell)上残留半个旧字。强制整屏重绘绕开
2686+ // 有问题的增量 diff。仅在「输入值实际变化 且 宽字符行中编辑态」时触发:日常行尾打字、
2687+ // 纯光标移动都不满足,零影响。
2688+ if m .input .Value () != beforeVal && m .inputWideMidLine () {
2689+ cmds = append (cmds , tea .ClearScreen )
2690+ }
26832691 }
26842692
26852693 return m , tea .Batch (cmds ... )
26862694}
26872695
2696+ // inputWideMidLine 判断输入框是否处于会触发 ultraviolet 宽字符 diff 双写的状态:
2697+ // 当前行含宽字符,且光标右边同一行还有内容(即行中编辑,而非行尾追加)。
2698+ // 这是 issue #113 残影的必要条件;满足时配合强制重绘规避。
2699+ func (m model ) inputWideMidLine () bool {
2700+ val := m .input .Value ()
2701+ if val == "" {
2702+ return false
2703+ }
2704+ lines := strings .Split (val , "\n " )
2705+ li := m .input .Line ()
2706+ if li < 0 || li >= len (lines ) {
2707+ return false
2708+ }
2709+ line := lines [li ]
2710+ // 本行无宽字符(显示宽度 == rune 数)→ 不可能触发。
2711+ if ansi .StringWidthWc (line ) <= len ([]rune (line )) {
2712+ return false
2713+ }
2714+ // 光标右边同行还有内容(行尾追加不触发 bug)。
2715+ return m .input .Column () < len ([]rune (line ))
2716+ }
2717+
26882718// syncFileMention 据当前输入值同步 @ 文件提及选择器状态:
26892719// - 处于提及态且缓存为空 → 遍历 workspace 构建文件列表缓存
26902720// - 退出提及态 → 清空缓存与选中索引(下次 @ 重新遍历,自动拾取新增文件)
0 commit comments