vscode 为扩展查找/替换功能,公开API ```markdown 为扩展查找/替换功能,公开API ```

edqdpe6u  于 4个月前  发布在  Vscode
关注(0)|答案(9)|浏览(69)

根据类似的票据,这是在你的专业领域。
我设计了一个 nicer regex syntax ,并编写了一个vscode扩展,允许人们使用它进行搜索和替换(但在谷歌搜索如何做到这一点时,我遇到了许多人询问类似的用例):

https://marketplace.visualstudio.com/items?itemName=sonoflilit.kleenexp
https://github.com/SonOfLilit/kleenexp/blob/master/vscode/kleenexp/src/extension.ts
不幸的是,用户体验被迫相当繁琐。特别是,我不能展示一个漂亮的查找小部件(很好)并且我不能实现搜索时输入(致命缺陷)。
因此,我想自愿设计和实现内置命令,将使各种查找/替换扩展用例成为可能。暂定设计(待正式化和审查):

阶段I

editor.actions.findWithArgs (链接)以及 editor.action.previousMatchFindActioneditor.action.previousMatchFindAction 将暴露一个 revealWidget 布尔参数(这样扩展就可以例如在不显示查找小部件的情况下更改搜索字符串,并且有自己的F3/Shift+F3按钮,这些按钮仍然不会显示UI)

阶段II

设计一种更深入地钩入搜索和替换行为的方法,以便扩展可以覆盖vscode中所有搜索/替换小部件的行为。由于预处理搜索字符串是我所能想象的唯一用例,也许我们应该将其限制为注册一个函数来预处理搜索字符串。从我的阅读文档来看,没有机制可以让扩展在给定事件上注册函数并返回值,所以我不确定你是否会批准这个,但至少对我的扩展来说这将是非常好的。我想我会在用户需要我的语法的显著百分比时再回来找你。

阶段III

以一种支持传统语法和设置不同语言的方式实现搜索小部件的语法高亮(已经在待办事项列表中作为 #147726 )。也许甚至检测组,在匹配项中着色组,从而将vscode变成regex101.com,并让用户非常非常高兴:

是的,我会自愿实现这个功能,但它将非常复杂(例如,因为Javascript正则表达式不给你匹配组的开始/结束索引),并且需要一些产品参与(例如,用于突出显示不同组的颜色是什么?)。

总结

无论如何,这就是梦想,让我们回到现实。如果我提交一个关于阶段I的设计提案,它会被审查吗?基于商定的设计提交的补丁会被接受吗?

4bbkushb

4bbkushb1#

感谢SonOfLilit提供的宝贵建议和精彩的撰写,我非常喜欢您将请求分成多个阶段的方式。

第一阶段很简单,让我觉得有意义的是暴露参数以允许扩展来揭示小部件,我们只需要检查一下是否有其他命令归档相同的行为,如果没有,欢迎PR。

对于第二阶段和第三阶段,我可能会交换它们,因为设计一种更深入地钩住搜索和替换行为的方法需要团队范围内的API和UX讨论,尤其是当我们在整个VS Code工作台中统一查找/替换体验时。这需要很长时间才能取得进展。

为搜索小部件实现语法高亮
我认为这是非常有价值的,我们可以通过在查找输入框中使用Monaco编辑器来实现这一点,但我不确定在一个Monaco编辑器内渲染另一个Monaco编辑器是否有些过于复杂。话虽如此,我愿意对此进行探索,看看我们能否用坚实的正则表达式语言语法高亮和验证器走多远。

zzwlnbp8

zzwlnbp82#

我目前的第一阶段设计是否可以接受?我应该开始编写代码吗?

gorkyyrv

gorkyyrv3#

@SonOfLilit,我很荣幸能够审阅您的PR。

eh57zj3b

eh57zj3b4#

我遇到了一些复杂的问题,无法实现我想要的功能:
我希望我的扩展能够复制 this._editor.getOption(EditorOption.find).cursorMoveOnType 的行为。
对于查找小部件来说,当输入到搜索字段时会触发 FindReplaceState._onFindReplaceStateChange ,然后到达这段代码,它会选择四种方式之一来调用 this.research(e.moveCursor, ....) :

private _onStateChanged(e: FindReplaceStateChangedEvent): void {
[..]
		if (e.searchString || e.isReplaceRevealed || e.isRegex || e.wholeWord || e.matchCase || e.searchScope) {
			const model = this._editor.getModel();

			if (model.isTooLargeForSyncing()) {
[..]
			} else {
				if (e.searchScope) {
					this.research(e.moveCursor, this._state.searchScope);
				} else {
					this.research(e.moveCursor);
				}
			}
		}

然而,当我们使用编辑器命令更改内容时,会调用 CommonFindController.start() ,它会执行以下操作:

protected async _start(opts: IFindStartOptions, newState?: INewFindReplaceState): Promise<void> {
		this.disposeModel();
[..]
		this._state.change(stateChanges, false);  // false is for .moveCursor

		if (!this._model) { // always true afaict because of the this.disposeModel()
			this._model = new FindModelBoundToEditorModel(this._editor, this._state);
		}
        }

即使我将 false 更改为 opts.moveCursor ,它也无法实现我想要的功能,因为 new FindModelBoundToEditorModel() 通过调用 this.research(false, ...) 来覆盖它。
你有什么建议给我吗?还是我应该继续尝试直到它能正常工作?

wsewodh2

wsewodh25#

好的,我刚刚给 FindModelBoundToEditorModel 添加了一个可选参数 moveCursor。它已经足够好用,我不介意让它更完美。

tcbh2hod

tcbh2hod6#

While working on this I stumbled on this change, which I think fixes a bug, but since I ended up choosing a different path it's not needed for my code and not part of the PR.

diff --git a/src/vs/editor/contrib/find/browser/findController.ts b/src/vs/editor/contrib/find/browser/findController.ts
index a91fce2fac5..5251c47bb12 100644
--- a/src/vs/editor/contrib/find/browser/findController.ts
+++ b/src/vs/editor/contrib/find/browser/findController.ts
@@ -603,7 +603,7 @@ export class StartFindWithArgsAction extends EditorAction {
 
                        await controller.start({
                                forceRevealReplace: false,
-                               seedSearchStringFromSelection: (controller.getState().searchString.length === 0) && editor.getOption(EditorOption.find).seedSearchStringFromSelection !== 'never' ? 'single' : 'none',
+                               seedSearchStringFromSelection: (args?.searchString?.length === 0) && editor.getOption(EditorOption.find).seedSearchStringFromSelection !== 'never' ? 'single' : 'none',
                                seedSearchStringFromNonEmptySelection: editor.getOption(EditorOption.find).seedSearchStringFromSelection === 'selection',
                                seedSearchStringFromGlobalClipboard: true,
                                shouldFocus: args?.shouldReveal === false ? FindStartFocusAction.NoReveal : FindStartFocusAction.FocusFindInput,
bqjvbblv

bqjvbblv7#

这个bug修复实际上确实很重要,我以错误的方式运行了测试。推送了它。

omqzjyyz

omqzjyyz8#

你好,

我的用户抱怨在vscode中发现了这个bug,我已经作为PR的一部分修复了它。我应该将它分成一个更小的PR吗?这样可以更快地获得CR和合并?

链接:https://github.com/microsoft/vscode/pull/156796/files#diff-c2c0a3f71ed0c733b8da6fe63824ea422fdbc76b47b82ab4afb772c4b2d11082R604

(它正在检查controller.getState().searchString,以确定是否应该从光标处获取搜索字符串,并忽略我们刚刚通过的新的searchString。结果是,第一次使用我的扩展搜索文档时,它会忽略你输入的内容,而是搜索光标下的内容,但从那时起,它的行为就正确了)

xpcnnkqh

xpcnnkqh9#

对不起让大家等了这么久。如果你仍然想合并这个PR,请尝试再次更新它以解决冲突,我会帮助审查并合并它。

相关问题