Skip to content

Releases: soybeanmilka/clipsift

v0.3.2

Choose a tag to compare

@github-actions github-actions released this 18 Oct 09:35

修了什么

0.3.1 里,点 × 收进托盘之后,左键点托盘图标(或菜单里的「显示窗口」)叫不回窗口——程序只能从任务管理器杀掉。

根因不是托盘,是窗口藏起来之后帧循环停了:

  • eframe 的每一帧都挂在 WindowEvent::RedrawRequested 上,而这个事件来自 WM_PAINT;
  • Windows 只给可见窗口派发 WM_PAINT;
  • 于是 Visible(false) 之后 egui 再也没跑过一帧(日志实测:藏起来之后 8 秒 0 帧);
  • 托盘点击其实收到了,只是堆在队列里没人取——没人跑帧,就没人取。

0.3.1 那个「心跳线程」发的是 request_repaint,对不可见窗口是空转,根本叫不醒。

怎么修的

  • 新增 taskbar::force_paint:藏起来时从外部线程 SendMessageW(WM_PAINT) 同步塞一帧进去。PostMessage(WM_PAINT) 和 RedrawWindow 都试过,对隐藏窗口全是 0 帧,只有 SendMessage 能叫醒。
  • 心跳线程改成事件驱动:每 120ms 只看一眼托盘事件队列空不空(只看不取,不能把事件消耗掉),真有事件才按可见性选路——可见走 request_repaint,藏起来走 force_paint。
  • 删掉隐藏期间的 1 秒定时重绘:对不可见窗口是纯空转。

副作用是好的:藏起来且没事件时零帧零 CPU,而 0.3.1 是无条件 8 帧/秒。

验证过什么

  • cargo test 64 passed(core 30 / cli 9 / gui 18 / 属性 7);cargo clippy --all-targets -- -D warnings、cargo fmt --check 干净。
  • 真机:debug 版点 × 藏起来 → 日志 3 秒零增长(确认真的没跑帧)→ 用 Win32 往进程的 tray_icon_app 窗口发一次左键 → 日志依次出现 图标事件 Click、翻译成 [Show]、处理托盘动作 Show,主窗口 IsWindowVisible 变回 true,帧号继续涨。
  • 托盘菜单的「退出」走同一条取事件的路,也能退(原来卡在同一个地方)。

下载

平台 文件
Windows(安装包,按用户装、不弹 UAC) ClipSift-setup.exe
Windows(免安装 zip) clipsift-windows-x86_64.zip
Linux x86_64 clipsift-linux-x86_64.tar.gz
macOS Apple Silicon clipsift-macos-aarch64.tar.gz

装过旧版的直接覆盖安装就行,规则配置会保留。

小提示:Win11 默认把新托盘图标塞进任务栏那个「⌃」溢出面板里,想让它常显,在「任务栏设置 → 其他系统托盘图标」里把 ClipSift 打开。


完整改动:v0.3.1...v0.3.2

v0.3.1

Choose a tag to compare

@github-actions github-actions released this 18 Oct 07:29

修了什么

点 × 把窗口收进托盘之后,任务栏上会留下一个点不动的按钮:屏幕上没有窗口,
任务栏里却有一个 ClipSift 按钮,点它什么都不会发生。关也关不掉、退也退不出,
只能去任务管理器杀进程。

为什么会这样

有托盘时,程序发的是 Visible(false),winit 把它翻译成 ShowWindow(SW_HIDE)——
只清掉了窗口的 WS_VISIBLE 位。可是窗口既没有被最小化,扩展样式里也还带着
WS_EX_APPWINDOW(普通应用窗口)、没有 WS_EX_TOOLWINDOW(工具窗口)。
Windows 的规则是:只要窗口没最小化又是普通应用窗口,就给它一个任务栏按钮。
于是就有了那个僵尸按钮。

程序唯一的出口本来是托盘菜单里的「退出 ClipSift」,但 Windows 11 默认把新注册的
托盘图标塞进任务栏那个「⌃」溢出面板里——用户根本看不到图标,也就找不到出口。

怎么修的

藏窗口时不再只改可见性,而是把窗口的扩展样式改成工具窗口
(清 WS_EX_APPWINDOW、设 WS_EX_TOOLWINDOW),Windows 就不再分配任务栏按钮。
从托盘唤回窗口时再把样式改回来。

为什么不用 egui/winit 的现成 API:ViewportCommand 里没有 SkipTaskbar 这一项,
winit 0.30 的公开 API 也没有 set_skip_taskbar(它只在内部实现里,走
ITaskbarList::DeleteTab)。运行时切换只能自己拿窗口句柄改。

验证过什么

  • 5 个单元测试覆盖样式位运算(藏/唤回各改哪些位、不相干的位不受影响、幂等、
    hide→show 往返)。往返测试一开始就抓到一个真 bug:唤回时只清了 APPWINDOW
    没清 TOOLWINDOW,藏过一次再唤回,窗口就永远变不回普通窗口。
  • 真机跑 debug 构建,点 × 前后用 Win32 查主窗口的 ex style:
    点 × 前 vis=true ex=0x00040110(带 APPWINDOW)
    点 × 后 vis=false ex=0x00000190(TOOLWINDOW,无 APPWINDOW)
  • 测试 59 → 64;clippy -D warnings 干净;cargo fmt --check 干净;CI 三平台全绿

已知限制

  • 托盘图标在 Win11 上默认可能被收进任务栏的「⌃」溢出面板。
    想常显的话:任务栏设置 → 其他系统托盘图标 → 把 ClipSift 设为开。
  • 非 Windows 平台没有托盘图标(Linux 要 GTK + libappindicator 一整套依赖,不划算),
    点 × 仍然是收进任务栏。

Full Changelog: v0.3.0...v0.3.1

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 17 Oct 19:22

Windows:双击安装(推荐)

下载 ClipSift-setup.exe 双击,一路下一步就行。
装完直接能用,卸载去「设置 → 应用 → 已安装的应用」找 ClipSift。

  • 装到当前用户目录,不需要管理员权限,不弹 UAC
  • 安装时可勾选「开机自动启动」「创建桌面快捷方式」
  • 卸载干净:程序文件、开始菜单、桌面图标、自启项一起清掉
  • 卸载时问一句要不要保留你的规则设置

0.3.0 新增:系统托盘

点 × 不再只是最小化——窗口收进右下角托盘,任务栏上也不留按钮,剪贴板守护继续跑。

  • 右键托盘图标:唤回窗口 / 开始守护 / 停止守护 / 立刻净化一次剪贴板 / 退出
  • 悬停提示:ClipSift · 守护中 · 已净化 N 次,跟着界面状态实时更新
  • 单击或双击图标都能唤回窗口(Win11 的溢出面板会吃掉单击,所以两个都认)
  • 非 Windows 平台、或者托盘建不出来时,自动退回「收进任务栏」的老行为,
    界面上会显示「(托盘不可用)」,不会让人找不到程序

托盘图标是专门重绘的 32×32 版本(强调色圆角方块 + 斜放的扫帚 + 三颗被扫走的白点),
缩到 16px 还认得出轮廓——窗口那枚 256 的图标直接塞进去会糊成一团。

实现上值得记的两个坑:

  • 心跳线程而不是 request_repaint_after:窗口被 Visible(false) 藏掉之后,
    eframe 会直接跳过排定的重绘帧(Windows 上只有非 0 尺寸的窗口才给发重绘),
    表现就是「点托盘图标没反应」。所以另起一个线程每 120ms 调 request_repaint——
    它走 PostMessage 那条路,不依赖窗口可见。
  • 必须在主线程建托盘:菜单要绑定窗口的消息循环,换线程建出来的菜单点了没反应。

其他方式

平台 文件 说明
Windows x64 clipsift-windows-x86_64.zip 免安装版,解压即用
Linux x64 clipsift-linux-x86_64.tar.gz 命令行
macOS Apple Silicon clipsift-macos-aarch64.tar.gz 命令行

命令行用法

clipsift watch         # 常驻后台,每次复制自动净化
clipsift once          # 只净化一次剪贴板
clipsift --list-rules  # 看有哪些规则

详见 README。

验证过什么

  • cargo test 59 个测试全过(core 30 / cli 9 / gui 13 / 属性测试 7)
  • cargo clippy --all-targets -- -D warnings 无警告,cargo fmt --check 干净
  • 三个平台 CI 构建
  • 端到端:一万条随机脏文本验证净化幂等(apply(apply(x)) == apply(x))

v0.2.1

Choose a tag to compare

@github-actions github-actions released this 17 Oct 13:54

Windows:双击安装(推荐)

下载 ClipSift-setup.exe 双击,一路下一步就行。
装完直接能用,卸载去「设置 → 应用 → 已安装的应用」找 ClipSift。

或者在命令行里:

winget install soybeanmilka.ClipSift

ClipSift 界面

  • 装到当前用户目录,不需要管理员权限,不弹 UAC
  • 安装时可勾选「开机自动启动」「创建桌面快捷方式」
  • 卸载干净:程序文件、开始菜单、桌面图标、自启项一起清掉
  • 卸载时问一句要不要保留你的规则设置

其他方式

平台 文件 说明
Windows x64 clipsift-windows-x86_64.zip 免安装版,解压即用
Linux x64 clipsift-linux-x86_64.tar.gz 命令行
macOS Apple Silicon clipsift-macos-aarch64.tar.gz 命令行

命令行用法

clipsift watch         # 常驻后台,每次复制自动净化
clipsift once          # 只净化一次剪贴板
clipsift --list-rules  # 看有哪些规则

这个版本验证过什么

从 Release 下载安装包回来,在本机完整跑了一遍:

  • 静默安装退出码 0,安装目录、两个 exe、开始菜单、uninstaller 全部落地
  • clipsift --version 报 0.2.1
  • 含 U+200B / U+00A0 / 弯引号的测试文本,净化后可疑字符 0 个
  • 静默卸载 1.5 秒完成,程序目录、开始菜单、桌面图标、注册表自启项全清
  • 图形卸载:中文界面正常,问「要保留你的规则设置吗」,选「是」后配置文件确实留下
  • winget 清单 winget validate 通过,SHA256 与这份安装包一致

详见 README。

v0.2.0

Choose a tag to compare

@github-actions github-actions released this 17 Oct 13:02

从复制粘贴里筛掉隐形字符:零宽空格、伪空格、弯引号、全角字母。
解决飞书 / 网页 / AI 聊天复制代码报 stray '\342'、IndentationError、VLOOKUP 匹配不上的问题。

Windows 用户:省事版

下载 clipsift-windows-x86_64.zip,解压,双击 clipsift-gui.exe —— 完事。
打开就在净化,勾上「开机自启」以后不用管它。

ClipSift 图形界面

下载

平台 文件 说明
Windows x64 clipsift-windows-x86_64.zip 含 clipsift-gui.exe(图形界面)和 clipsift.exe(命令行)
Linux x64 clipsift-linux-x86_64.tar.gz 命令行
macOS Apple Silicon clipsift-macos-aarch64.tar.gz 命令行;首次运行可能需 xattr -d com.apple.quarantine clipsift

命令行用法

clipsift watch         # 常驻后台,每次复制自动净化
clipsift once          # 只净化一次剪贴板
clipsift --list-rules  # 看有哪些规则
clipsift --merge       # 把 PDF 那种硬换行还原成段落

它治什么

场景 报错 真凶
网页复制 C++ stray '\342' in program U+200B 零宽空格
飞书复制 Python IndentationError 缩进是 NBSP 不是空格
Word 复制代码 满屏语法错误 全角标点 + 弯引号
Excel 导出 CSV VLOOKUP 匹配不上 单元格尾部有 U+00A0

按报错原文查 → 常见报错速查表
飞书场景详解 → 从飞书复制代码为什么老是报错

0.2.0 的改动

  • 新增图形界面 clipsift-gui.exe:规则开关、实时预览、守护启停、开机自启、浅深色主题、内嵌中文字体
  • 全角字符拆成两档:全角字母数字转半角(默认开),全角标点转半角(默认关,因为中文正文里那些标点本来就是对的)
  • 可疑字符按危害排序:隐形字符排最前,其次是会引发语法错的全角运算符
  • 关窗口不退出(收进任务栏继续守护),只有点「退出」才真退
  • 无控制台弹窗(GUI 子系统编译)

详见 README · English

MIT License

ClipSift 0.1.0 — 剪掉复制粘贴里的隐形字符

Choose a tag to compare

@soybeanmilka soybeanmilka released this 17 Oct 12:10

一句话

从复制粘贴里筛掉隐形字符——零宽空格、伪空格、弯引号、全角字母。

从飞书 / 钉钉文档 / Notion / AI 聊天窗口复制代码,编译报 stray '\342' in program、IndentationError、VLOOKUP 匹配不上?下载它。

安装

平台 下载 说明
Windows x64 clipsift-windows-x86_64.zip 解压出 clipsift.exe,放进 PATH(如 C:\Users\<你>\.cargo\bin)
Linux x64 clipsift-linux-x86_64.tar.gz tar -xzf 后 sudo mv clipsift /usr/local/bin/
macOS Apple Silicon clipsift-macos-aarch64.tar.gz tar -xzf 后 mv clipsift ~/.local/bin/(首次运行可能要 xattr -d com.apple.quarantine clipsift)

装好后跑一次:

clipsift watch

之后每次复制,剪贴板自动净化。单个可执行文件,无任何运行库依赖。

它治什么

你遇到的现象 真实原因 ClipSift 怎么处理
C/C++ 编译报 error: stray '\342' in program 行里混进了 U+200B 零宽空格 直接删掉
Python 复制后 IndentationError: unexpected indent 缩进是 U+00A0 不间断空格 归一成 ASCII 空格,宽度不变
代码里满是语法错误 中文弯引号 + 全角标点 转成 ASCII
Excel/ERP 导出的数据 VLOOKUP 匹配不上 单元格尾部有 U+00A0 归一成普通空格
命令行 command not found 但看着一模一样 复制了不间断空格当普通空格 归一成普通空格
源码里藏着看不见的指令 U+E0000 Unicode Tag / bidi 覆盖符 删掉

边看边用

常用命令

clipsift watch                # 常驻后台,每次复制自动净化(最常用)
clipsift autostart enable     # 开机自动守护,无窗口(免管理员权限)
clipsift once                 # 只净化当前剪贴板一次
clipsift -f dirty.txt         # 净化文件
clipsift inspect < dirty.txt  # 先看看脏在哪
clipsift --report < dirty.txt # 净化并给统计
clipsift --list-rules         # 看所有规则
clipsift --off fullwidth      # 关掉某条规则

验证过的

  • 41 个测试全绿,其中 7 个属性测试拿一万条随机脏文本验证幂等性
  • cargo clippy --all-targets -- -D warnings 零警告
  • 文件级两次净化 SHA256 一致
  • 剪贴板守护进程实测:复制带 U+200B + U+00A0 的文本,2 秒内自动变干净
  • 本 Release 的产物是从 GitHub 下载回来重新验证的:Windows exe 实跑净化 + 幂等 + 剪贴板,
    Linux 包确认为 ELF 64 位,macOS 包确认为 Mach-O arm64

已知边界

  • 剪贴板监听目前只支持 Windows。命令行净化(文件 / stdin)三个平台都能用。
  • --merge(合并硬回车)不是幂等的,按设计就是一次性变换,只适合把 PDF 正文摊平。默认关闭。
  • macOS 只有 Apple Silicon(arm64)版本。Intel Mac 请自行 cargo build --release。

许可

MIT