“选择词”BBEdit脚本

Triple-clicking is the standard mouse gesture to select an entire line at onceBut what if your hands are on the keyboard? BBEdit, not surprisingly, has you covered编辑→选择行命令(默认快捷方式:Cmd-L)选择当前行A companion command, Select Paragraph (default shortcut: Cmd-Opt-L), takes things one step further: it selects the current line, as well as all adjacent lines that contain anything other than whitespace.

I use both these commands frequently; editing in an application that doesn’t support them drives me nuts它们在我的肌肉记忆中根深蒂固,就像全选的Cmd-A快捷方式一样BBEdit支持这两个命令至少早在1993年的2.5版本,这是最古老的版本的用户手册我已经躺着。

一段时间,在我看来,我想要一个第三,类似的命令:选择单词在同样的方式,选择线就像一个三击,将像一个双击选择词:位置插入点内部或下一个词,调用Select命令,和这个词将被选中,就像如果你双击运行如果你有部分文字选中,选择单词将扩大选择整个单词。

不需要文件特性请求梗概,然而,这个命令可以使用AppleScript实现(它在Mailsmith工作。)

我第一次在它工作,但有些复杂I went about it the long way, by first finding the character position offset of the last word between the beginning of the document and the current selection; then selecting the first word after that offsetYou don’t want to see that script; it’s junk.

我从中学到了正确的方法肖恩·斯坦利发布一条消息2002年3月的BBEdit-Scripting邮件列表这是一个稍微改写版本斯坦利的脚本:

tell application "BBEdit"
   tell window 1
      set sel_offset to characterOffset of selection
      select (last word whose characterOffset ≤ sel_offset)
   end tell
end tell

这个脚本实现了选择词在两行命令(不包括告诉语句)。

第一行会抵消当前的选择一个characterOffset是一个整数值,对应文档中的一个字符的位置,从1总是有一个选择——一个插入点计数作为任意选择两个字符之间因此,characterOffset选择告诉你选择开始的地方。

第二行是我们确定哪些单词“当前”并选择它这是一个很多一行AppleScript行动的使用谁的clause is essential; see my brief介绍上周的条款如果你不熟悉它们。

在本例中,我们使用一个谁的条款来创建一个过滤参考每一个字和一个偏移量小于当前选择的抵消其实,小于或等于,所以当插入点定位在一个单词的开始,我们会选择这个词,而不是前一个(生成一个在AppleScript迹象,只需输入“< =” in your script editor; when the script is compiled it’ll be turned into a genuine)。

的这些话,我们感兴趣的是最后一个AppleScript关键字持续返回一个列表的最后一个元素同样,我们可以要求(词1的characterOffset≤sel_offset); asking for the -1st element of a list returns the last item, the -2nd the second-to-last, etc.

一旦我们有参考我们想选择这个词,我们可以简单地告诉窗口以选中它能够告诉窗口选择一个单词听起来很明显,而且确实很方便,但是如果你想一想,那就太漂亮了长路线是确定目标词的长度和偏移量,然后指定一个范围的字符的对象选择命令。

得到具体的

在这一点上,乍一看,它看起来像我们做完了However, this script has a serious performance problem which will only appear when the script is invoked in largish documents (where by “largish”, I mean more than a few hundred lines or so; the exact point where performance goes from fast to slow isn’t important.)

这个问题从我们的结果谁的条款We ask for every word with an offset less than the offset of the current selection; what’s implied in this谁的条款是我们要求的窗口中的每个字的偏移量小于选择抵消呢在一个相当大的文档,这可能是成千上万的单词而不是运行的瞬间,小文档,可能需要几秒钟——这不是灾难性的,但这是恼人的足以击败脚本的目的。

通过的力量谁的作为脚本编写者,我们不需要分配临时列表变量来保存窗口的每个单词,也不需要测试每个单词以查看其偏移是否符合我们的标准但这项工作仍然必须执行——这是在幕后,AppleScript。

假设您拥有一个机器人,你住在一个小岛你开始饿了吃午饭,所以你告诉你的机器人出去找到离你家最近的餐厅,现摘的薯条机器人离开,找到岛上的每个餐厅,供应新鲜的薯条,计算每个餐馆到你家的距离,然后在离开后半小时返回结果。

现在想象一下,你和你的机器人从小岛在北美如果你随后给机器人发出了相同的命令,那就是过去的午餐时间当你的机器人到家结果(甚至更久如果机器人管理穿越巴拿马运河。)

给定的命令,没有规模You instead should say something like, “Find the closest restaurant that serves fresh-cut fries, within five miles of home.” Now, no matter where you live, your robot will return with the answer within a reasonable period of time.

这大致类似于问题谁的我们脚本中的子句我们需要的是更多的特异性,所以AppleScript不需要问BBEdit返回一个列表,每一个字在整个文档我们的脚本的本质是,我们正在寻找这个词总是在同一行选择因此,而不是问的每一个字文档其偏移量小于选择偏移量,我们可以改为询问当前的每个字有这样一个偏移量:

tell application "BBEdit"
   tell window 1
      set sel_offset to characterOffset of selection
      set cur_line to startLine of selection
      select (last word of line cur_line ¬
         whose characterOffset ≤ sel_offset)
   end tell
end tell

此脚本将表现不佳仅当当前行非常长,就像在thousands-of-words-on-a-single-line长我们甚至可以进一步孤立的可能性与BBEdit合作的问题显示线而不是常规线。

在BBEdit,普通是一个运行的文本,由回归即使你有soft-wrapping打开,屏幕上那长长的队伍包装,由返回这些也被称为“硬线”(在英语中,不是AppleScript)一个display_line也就是所谓的“软线”,就是你在屏幕上看到的如果soft-wrapping是关闭的,display_lines都是一样的注意强调“display_line” — this was a nomenclatural decision Bare Bones made to avoid ambiguity; if it were a space instead of an underscore, it might look like the verb显示后跟对象类

切换到display_lines给我们:

tell application "BBEdit"
   tell window 1
      set sel_offset to characterOffset of selection
      set cur_line to startDisplayLine of selection
      select (last word of display_line cur_line ¬
         whose characterOffset ≤ sel_offset)
   end tell
end tell

这个脚本只会带来性能损失在罕见的情况下,你有非常长的行文本和soft-wrapping是关闭的。

最后一次联系,致命一击,那么我们就完成了,脚本让略有不明显的假设——即,当前display_line包含至少一个词和一个偏移量小于或等于选择偏移量如果没有 - 比如说插入点是在空行的开头,还是以空格开头的行 - 脚本将生成错误(原始的脚本,也有类似的,但更明显的假设:整个窗口的文本包含至少一个词前选择。)

解决方案是使用一个试一试块,如果我们抓住一个错误,做点有用的事情一个合理的操作是选择整个当前行所以,最后的脚本:

tell application "BBEdit"
   tell window 1
      set sel_offset to characterOffset of selection
      set cur_line to startDisplayLine of selection
      try
         select (last word of display_line cur_line ¬
            whose characterOffset ≤ sel_offset)
      on error
         select display_line cur_line
      end try
   end tell
end tell

附言:失踪但明显优化

可以说上述场景中的假设机器人应该能够交易,优雅,与原来的非特异性的命令即使没有任何形式的“常识”AI,鉴于我们要求最亲密的餐厅提供新鲜薯条,一旦机器人发现了一个这样的餐厅,它可以在理论上足够聪明,他不要冒险在家里任何进一步的,因此继续只搜索餐馆比一个更接近已经发现。

同样,由于我们专门问的持续具有小于(或等于)选择偏移的偏移的字,理论上,可以优化该查询,使得不需要为临时列表确定和分配内存。每一个词在文档中它只需要从当前选择倒退,找到一个词但这不是AppleScript是如何工作的,所以我们也没有假设的机器人。

事实上,也没有理由返回一个列表的成千上万的单词不能很快发生按照现代标准,一个只有“数千”元素的列表/数组应该被快速分配和迭代I’m honestly unsure whether this problem is due to (a) inefficiencies in the current AppleScript engine itself; (b) constraints on the size of data passed through Apple events; (c) BBEdit’s handling of the谁的clause Apple event; or (d) some combination of more than one of the above factors然而,在BBEdit的辩护,我看到类似的(如果不是更糟)性能限制其他text-suite精明的脚本编辑器希望在不久的将来某个时候,AppleScript能够快速有效地处理更大的数据集。