幽灵剪切:为什么剪切与粘贴到处都是坏的
文章摘要
作者(Textualize 的 Will McGugan,即 Rich / Textual 的作者)在这篇文章里主张:几乎每一个文字处理器、代码编辑器和浏览器文本框里的「剪切与粘贴」都存在设计缺陷,并提出了一个替代方案,他称之为「Ghost Cut(幽灵剪切)」。
他列举了传统剪切的三个问题。第一,剪贴板的改动不可撤销。撤销(undo)会把文本恢复到文档里,但剪贴板的内容已经被永久覆盖了——「如果你后悔替换掉剪贴板里的内容,那太糟了,它们已经消失在数字以太中。」第二,剪切会导致文档重排。剪切和粘贴的目的几乎总是「移动文本」,但你一按下剪切,文档立刻重排,于是你得重新找一遍要粘贴的位置。他承认这只是很小的认知负担,但认为是不必要的负担。第三,剪切与粘贴不是原子操作。即使中间没有任何编辑,要撤销「剪切+粘贴」也需要按两次撤销:第一次移除新粘贴的文本,第二次才恢复原位置的文本。
Ghost Cut 的方案是:按下 Ctrl+X 后,被选中的文本淡化并变为惰性——你无法点击它,光标会直接跳过它,但它仍然留在文档里,文档不重排。此时什么都没有进剪贴板,也就没有任何需要撤销的东西。如果你改变主意,按 Esc 就能把文本恢复为可编辑状态。按下 Ctrl+V 时,淡化的文本被移除、并出现在光标位置——整个移动作为一次可撤销的操作完成。这套方案保留了原有的肌肉记忆(还是 Ctrl+X / Ctrl+V),同时消除了剪贴板污染并实现了单步撤销。至于那些确实想要传统剪切语义的场合,作者的答案是:用 Ctrl+C 复制,然后按退格删除——两个键而不是一个键;他说自己极少用到「剪切但不粘贴」,所以这笔交易明显划算。作者呼吁各家文本编辑器广泛采纳,同时承认在代码编辑器里这个论证要弱一些。
文章在 HN 上得了 194 分和 150 条评论,但评论区的主流态度是不买账。反对意见集中在几点:剪贴板是操作系统级的共享状态,而撤销栈是应用级的,把两者耦合起来会制造更多问题;「剪切一次、粘贴多次」是很多人真实存在的工作流;「剪切然后撤销」被相当多人当作带视觉反馈的复制在用;以及最根本的一点——这不是缺陷,而是不同的心智模型。也有不少人指出,作者想要的「原子移动」其实早就存在,它叫拖放(drag & drop)。
HN 评论精华
-
throwawayffffas 写了最完整的反驳:剪切与粘贴是三个操作。剪切本身就是复制加删除,复制从来不会被撤销撤掉,那么剪切也不该被撤掉。「我每天都要剪切、撤销、……、撤销、然后粘贴好几次。这是功能,不是 bug。」他追问了一串 Ghost Cut 没回答的问题:如果你粘贴多次会怎样?先粘贴被剪切的文本,然后呢?粘贴剪贴板里之前的东西?为什么我不粘贴的时候我的编辑器还要去读剪贴板(为了实现回滚)?如果里面有一个密钥,我们就直接交给 Copilot 或者随便哪个正在运行的扩展?他也指出文件管理器里的「剪切/粘贴」是个糟糕的类比——那实际上是 move,「剪切」填第一个参数、「粘贴」填第二个参数,所以才会灰显、才会在粘贴前什么都不做;文件系统没有剪贴板,而且在文件管理器里你极不可能想粘贴到多个位置,这在文本编辑器里恰恰不成立。他最后补了一句相当中肯的话:他不是说这套语义不好,各有所好,但这完全是另一个操作,甚至根本不需要剪贴板——你可以用一个单独的快捷键让文本变灰再移到想要的位置,整件事就是原子的、叫 move、而且在所有方面都更干净。
-
Wowfunhappy 的分析被广泛认可:确实剪切粘贴会重排两次(剪切时一次,粘贴时一次),但它重排的位置正是你眼睛已经在看的地方;Ghost Cut 只重排一次(粘贴时),但重排在你眼睛不在的地方,从视频看这反而更让人困惑。至于「不是原子操作」——Ghost Cut 也不是,因为如果你只剪切不粘贴,你就停在一个灰色文本的中间态。他唯一同意的是第三点「剪切可撤销」,而且认为这可以轻易修好:如果你撤销一次剪切,就把剪贴板里之前的内容放回去;「如果只有一个应用这么做会很困惑,但如果操作系统在系统级实现它,我认为这是个好改进。」drdexebtjl 指出了这个方案的硬伤:撤销通常是文件级或应用级的,剪贴板却是共享的——你可以在 A 应用剪切、切到 B 应用剪切别的东西、再回到 A 撤销那次剪切。Wowfunhappy 提出可以在应用层判断剪贴板内容是否还是当初剪切的值,是就还原、否则什么都不做;drdexebtjl 反问撤销之后剪贴板里该是什么,并给出结论:「问题在于用户不会预期撤销的行为取决于他在另一个程序里做了什么。撤销永远不动剪贴板才是更一致、更好的 UX。」两人最后达成了一致:「我同意!这里没什么需要修的。」0gs 则被激发出另一个想法:「哇,操作系统级的撤销会是这个问题酷得多的解法。」
-
Diogenesian 的框架被很多人引用:这读起来像是「剪切的默认行为做了一些不契合作者个人心智模型和工作流的可用性选择」,这完全站得住脚,但把它描述成「缺陷」而不是「选择」就很奇怪了。最明显的例子就是第一条:一次误操作的剪切,通常本意是复制而不是删除,所以把文本留在剪贴板里是合理的设计。「我认为大多数人理解的『撤销』是『撤销对文件的改动』,而不是『撤销对文件的改动 + 操作系统状态』。」
-
blt 给出了一个非常自然的反例工作流,被多人赞同:做一堆编辑 → 觉得不都喜欢 → 复制想留下的部分 → 撤销一堆 → 粘贴好的部分。Mogzol 澄清说文章并不主张剪贴板状态该进撤销栈,而是主张剪切根本不该碰剪贴板;Dylan16807 立刻抓住要点:那我怎么在程序之间剪切粘贴?粘贴现在是一半时间用剪贴板一半时间不用?Mogzol 确认这正是文章的意思——剪切(以及粘贴被剪切的内容)完全发生在同一个应用内,要放到别的程序就必须用复制。
-
「剪切+撤销 = 带反馈的复制」是评论区最出人意料的高频用法。sharkjacobs:「我经常剪切再撤销,因为看到那一剪就是告诉我内容成功进入剪贴板的反馈。这件事并不总有保证,尤其在网页应用里,有时候我只是焦点落在了错误的窗口上。」croes 说得更直接:「你从没有过复制、然后粘贴、结果粘出来的是别的东西,因为复制失败了吗?剪切+撤销就是带视觉反馈的复制。」lloydatkinson 描述了同一个痛点的另一面:他一开始以为文章要讲的是那个人尽皆知的问题——明明复制了好几次,剪贴板里还是没有内容;他甚至养成了在 Chrome 里连按半打 Ctrl+C 以确保真的生效的习惯。jimjimjim 一句话总结:「剪切粘贴没坏,是复制坏了(在 Windows 上)。我复制粘贴的肌肉记忆现在是 ctrl-c、ctrl-c、ctrl-c、ctrl-v。」efreak 提供了另一种反馈技巧和一个额外用途:粘贴动作本身就有反馈(光标会移到替换后的文本末尾),而且他会故意用复制在不打算修改的文档的撤销历史里打标记,这样就能用撤销历史在不同区域之间跳转。jubilanti 建议装个剪贴板管理器配上通知和指示器就不用这么折腾;nkrisc 反驳「为了解决这个问题去装更多软件似乎比问题本身更糟」,michaelmrose 回一句「连 Windows 都开箱自带这个软件,因为它太明显有用了」。
-
kps 贡献了最有价值的历史考据:Xerox Star 根本没有剪切/复制/粘贴,它有的是对当前选区的「copy to」和「move to」操作,更接近今天的拖放。「某些有影响力的人认定,不可见且脆弱的剪贴板状态比一个进行中的复制/移动状态更好。」panic 补上了 Larry Tesler(那个「NOMODES」车牌的男人)2012 年的历史回顾论文:Tesler 反对「move to」的理由是它会把你逼进一种模式,你必须立刻挑选目的地。「我很好奇当年有没有人提出过 OP 这个方案——它看起来确实是个有希望的中间地带。」QuercusMax 补充:「大概是被认为太模态了。模态 UI 有很长一段时间非常不时髦。」
-
多人指出这个功能早就存在:wasabi991011「『Ghost cut』确实存在于 VSCode、Word、GDocs 等等,它叫 move,你用鼠标拖动选中的文本就行」;xnx 和 clircle 同样第一反应是拖放(clircle 还补充拖放对无法剪切的数据极其有用,比如把邮件附件从一封草稿拖到另一封)。但 kmoser 提醒这假定了你 a) 有鼠标、b) 想用鼠标——有些人是键盘导向的,觉得鼠标太慢/太不精确。FabHK 指出在 macOS 上这基本就是拖放。
-
Excel 成了这场辩论的核心战场,因为它已经在做类似 Ghost Cut 的事。tectec 开门就说:「我不觉得我会喜欢这个。他提到 Excel 做了类似的事,而 Excel 是我最不喜欢做剪切/复制/粘贴的应用。」AndroTux:「我总觉得 Excel 会先想清楚在我这个意图下什么是最糟的剪切/复制/粘贴方式,然后精准地做那个。」Noumenon72 描述了自己的绕行方案:复制文本 → 粘贴 → 回去删掉原文,因为正常的剪切粘贴会破坏所有引用到粘贴目标的公式。但 FabHK 为 Excel 做了一段相当漂亮的辩护:Excel 复杂是因为你不只有单元格的内容,还有对单元格的引用;剪切和复制有微妙但合理的差异——绝大多数剪切后面只跟着一次粘贴,本质上构成一次原子移动,所以剪切粘贴后所有指向被移动单元格的引用都会更新,无论它们在移动区域内外、无论相对还是绝对引用(就像你在被引用单元格上方或左侧插入/删除行列时它们自然会更新一样);这也是为什么剪切会「标记」单元格、粘贴后标记消失、且不能粘贴两次——这正是文章里描述的 Ghost Cut。而复制则相反:只有被移动单元格中的相对引用会更新,复制区域保持标记状态,你可以反复粘贴。eviks 反驳这套「按频率优化心智模型」的思路:现实中你有两个不同的心智模型,降低不匹配的频率只是降低频率而已。
-
rickydroll 提出了整场讨论里最有分量、也最少被回应的角度:剪切粘贴是一次 UI 失败,它只在你双手功能完全正常时才勉强可用——如果你的手不好使、有颤抖或其他行动障碍,剪切粘贴的成功率会显著下降。「Emacs 的 mark-and-point UI 对所有人都有效:健全的手、部分功能的手,甚至语音识别。它也解决了文章描述的复制、剪切、粘贴问题。」rpdillon 顺着补充:文章明显对 Emacs 不熟——「替换剪贴板」这个 bug 在 Emacs 里不存在,因为 Emacs 有 kill ring(他甚至多年前买下了 killring.org);「文本重排」问题也被
C-u C-space遍历 mark-ring 完全解决;至于「多个操作」,他不认为那是 bug——多个操作是好事,因为他可以按自己的工作流去组合它们。 -
ethin 提出了可访问性上的实际疑问:淡化甚至不可见的文本往往依然存在于可访问性树中,能被辅助技术检测到。那么这个「淡化」操作会不会把被剪切的文本从可访问性树里移除?如果不会,那么这次「淡出」对屏幕阅读器用户来说等于什么都没发生,只会造成困惑。
-
layer8 找出了一个未定义的边界情形:如果你在两个不同区域上按了两次 Ctrl+X,然后按一次 Esc 会怎样?会恢复到第一次 Ctrl+X 之后的状态吗?所以 Ctrl+X 是往一个「待剪切栈」上压、Esc 是弹出?大概不是。「总之,这看起来是把『无法撤销剪贴板状态改动』换成了『无法回到更早的待剪切状态』。」gbalduzzi 列了同一类问题:如果我从来不粘贴,它会一直保持淡化吗?如果我在粘贴前复制了别的东西(也许在另一个应用里),我粘贴的是淡化的那段还是新复制的?「如果不走那条快乐路径,收益如此微小而麻烦如此多。」Y444 直指命门:「『按 Esc 会恢复文本』——这是整件事的致命缺陷,有了它它就不再是一个可以直接替换的方案。」
-
abanana 和 cyanydeez 代表了「别改约定俗成的行为」这一派。abanana:「剪切动作理应立刻把内容放进剪贴板,这样你想的话就能把它粘到别的程序里。觉得自己更懂,真的不是打破用户预期和正常工作流的理由。你的想法很可能是好的,但为了少数人的改进去为大多数人打破它,不值得。」cyanydeez 给了个具体的血案(并附了 issue 链接):「首先,不要默认覆盖标准行为,opencode 正在这么干。当我进入状态流时,一切都崩了——我想复制点东西,它声称在复制,但不,那是在 putty 里,那只是一行该死的文本。」
-
reichstein 的评价颇为犀利:「夸张的标题一如所料地误导。『Ghost cut』是一个两步的文本移动,一个完全合理的操作,正因为它和『一次剪切后跟一次粘贴』不是同一件事。剪切可以不配粘贴使用,粘贴可以用多次,它们是可组合的原语。有时你想要的不是那个组合,有时是。但声称它们坏了……这不像一个能看到自己需求和偏好之外的人。」
-
bambax 是少数完全站在作者一边的人:「我在所有点上都同意原文,因此强烈不同意这条帖子里说的一切。『剪切+粘贴』应该是一个原子操作。如果你想粘贴多次(为什么?什么场景?),那就复制到剪贴板然后粘贴到你心满意足为止。撤销剪切不撤销它的副作用也是一个根本缺陷。撤销应该永远意味着:把世界/系统的状态恢复到之前,而不是『按这个或那个情况回退几步』。」eviks 反问:那你复制之后撤销,你是想恢复剪贴板而不是撤销上一个应用动作?还是也该撤销鼠标移动?光标移动?「世界的状态」毕竟也包括光标在别的地方。throwawayffffas 加了一句嘲讽:「何必止步于此,把时钟也拨回去吧,再给所有远端主机发请求把我们的包送回来。」
-
关于格式的怨气也不小。foo12bar 说他真希望被讨论的是每个应用都拼命往剪贴板里塞格式信息(甚至塞进表格单元格的格式数据)这件事——他 50 多年的人生里大概有两次觉得这有用,其余时候是巨大的麻烦,包括让邮件客户端崩溃或拒绝正确撤销那些意外粘进来的诡异表格格式;他的可靠做法是先粘到终端里的编辑器再复制一次。ryandrake 把问题摊开:有些应用提供了区别于「粘贴」的「无格式粘贴」,但那个往往会去掉超链接,而超链接你通常是想留的。「『粘贴』这个习语已经被彻底压到极限了。粘贴该只粘文字?该包含文字颜色?背景色?字体?字号?该包含超链接这类附加元数据?」theowaway 也是同一句:「为什么这篇文章不是关于带格式粘贴这个怪物?」
-
giancarlostoro 点出了一个更实际的元凶:如果你误按了 Ctrl+C(本想按 Ctrl+V),Teams、Discord 等应用会复制一个空的输入框,并顺手清空你的剪贴板。「这就是复制粘贴多年来都是坏的原因,因为这些漂亮公司的开发者决定让你在
chatInputText.length === 0时擦掉终端用户的剪贴板。我注意到 Teams 普及后人们开始持续遇到复制粘贴问题,一直想不通,直到我意识到这一点。如果你在这些聊天公司工作,看在上帝的份上开个内部工单,这太丢人了。」EPWN3D 描述了同一个问题的 Windows 版本,并指出正确答案:「是的,在严格的工程意义上这是正确且最不意外的行为。但它很蠢,而且几乎必然不是我想要的结果。我的预期是 macOS 在这种情况下的做法——什么都不做。」 -
几个轻松的旁注:ericyd「别人会为什么事情激动起来总是让我惊讶。我这辈子从没对剪切粘贴有过任何感觉。」pizzalife「用了 30 年电脑,我一次都没用过剪切粘贴。」trgn「我自认还算能干,在技术生涯里达到了常规的里程碑,做过这个那个,然后我读着这个,一边点头,一边基本上搞不懂剪切粘贴到底有什么问题,是有一个,是哪个来的?总之,中年是真的,各位。」bighead1 最不客气:「想感谢这篇文章的作者,给了我一个机会去庆幸我这一生都不必承受他的观点带来的后果。想象一下这人当你的室友!」