diff --git a/lib/find-view.js b/lib/find-view.js index 3fb351bd..2759f0a8 100644 --- a/lib/find-view.js +++ b/lib/find-view.js @@ -79,8 +79,12 @@ class FindView { ), $.div({className: 'input-block-item'}, - $.div({className: 'btn-group btn-group-find'}, - $.button({ref: 'nextButton', className: 'btn btn-next'}, 'Find') + $.div({className: 'btn-group btn-group-find-prev'}, + $.button({ref: 'prevButton', className: 'btn btn-prev'}, '<') + ), + + $.div({className: 'btn-group btn-group-find-next'}, + $.button({ref: 'nextButton', className: 'btn btn-next'}, '>') ), $.div({className: 'btn-group btn-group-find-all'}, @@ -100,8 +104,12 @@ class FindView { ), $.div({className: 'input-block-item'}, - $.div({className: 'btn-group btn-group-replace'}, - $.button({ref: 'replaceNextButton', className: 'btn btn-next'}, 'Replace') + $.div({className: 'btn-group btn-group-replace-prev'}, + $.button({ref: 'replacePrevButton', className: 'btn btn-prev'}, '<') + ), + + $.div({className: 'btn-group btn-group-replace-next'}, + $.button({ref: 'replaceNextButton', className: 'btn btn-next'}, '>') ), $.div({className: 'btn-group btn-group-replace-all'}, @@ -223,7 +231,8 @@ class FindView { handleEvents() { this.findEditor.onDidStopChanging(() => this.liveSearch()); - this.refs.nextButton.addEventListener('click', e => e.shiftKey ? this.findPrevious({focusEditorAfter: true}) : this.findNext({focusEditorAfter: true})); + this.refs.prevButton.addEventListener('click', () => this.findPrevious({focusEditorAfter: true})); + this.refs.nextButton.addEventListener('click', () => this.findNext({focusEditorAfter: true})); this.refs.findAllButton.addEventListener('click', this.findAll.bind(this)); this.subscriptions.add(atom.commands.add('atom-workspace', { 'find-and-replace:find-next': () => this.findNext({focusEditorAfter: true}), @@ -235,6 +244,7 @@ class FindView { 'find-and-replace:use-selection-as-replace-pattern': this.setSelectionAsReplacePattern.bind(this) })); + this.refs.replacePrevButton.addEventListener('click', this.replacePrevious.bind(this)); this.refs.replaceNextButton.addEventListener('click', this.replaceNext.bind(this)); this.refs.replaceAllButton.addEventListener('click', this.replaceAll.bind(this)); this.subscriptions.add(atom.commands.add('atom-workspace', { @@ -726,8 +736,14 @@ class FindView { if (editor && (!hadFindTooltip || isDisabled)) { this.refs.findAllButton.classList.remove('disabled'); + this.refs.prevButton.classList.remove('disabled'); this.refs.nextButton.classList.remove('disabled'); + this.findTooltipSubscriptions.add(atom.tooltips.add(this.refs.prevButton, { + title: "Find Previous", + keyBindingCommand: 'find-and-replace:find-prev', + keyBindingTarget: this.findEditor.element + })); this.findTooltipSubscriptions.add(atom.tooltips.add(this.refs.nextButton, { title: "Find Next", keyBindingCommand: 'find-and-replace:find-next', @@ -740,8 +756,12 @@ class FindView { })); } else if (!editor && (!hadFindTooltip || !isDisabled)) { this.refs.findAllButton.classList.add('disabled'); + this.refs.prevButton.classList.add('disabled'); this.refs.nextButton.classList.add('disabled'); + this.findTooltipSubscriptions.add(atom.tooltips.add(this.refs.prevButton, { + title: "Find Previous [when in a text document]" + })); this.findTooltipSubscriptions.add(atom.tooltips.add(this.refs.nextButton, { title: "Find Next [when in a text document]" })); @@ -760,8 +780,14 @@ class FindView { if (canReplace) { this.refs.replaceAllButton.classList.remove('disabled'); + this.refs.replacePrevButton.classList.remove('disabled'); this.refs.replaceNextButton.classList.remove('disabled'); + this.replaceTooltipSubscriptions.add(atom.tooltips.add(this.refs.replacePrevButton, { + title: "Replace Previous", + keyBindingCommand: 'find-and-replace:replace-prev', + keyBindingTarget: this.replaceEditor.element + })); this.replaceTooltipSubscriptions.add(atom.tooltips.add(this.refs.replaceNextButton, { title: "Replace Next", keyBindingCommand: 'find-and-replace:replace-next', @@ -774,8 +800,12 @@ class FindView { })); } else { this.refs.replaceAllButton.classList.add('disabled'); + this.refs.replacePrevButton.classList.add('disabled'); this.refs.replaceNextButton.classList.add('disabled'); + this.replaceTooltipSubscriptions.add(atom.tooltips.add(this.refs.replacePrevButton, { + title: "Replace Previous [when there are results]" + })); this.replaceTooltipSubscriptions.add(atom.tooltips.add(this.refs.replaceNextButton, { title: "Replace Next [when there are results]" })); diff --git a/spec/find-view-spec.js b/spec/find-view-spec.js index 68385b1c..2e07b248 100644 --- a/spec/find-view-spec.js +++ b/spec/find-view-spec.js @@ -472,6 +472,7 @@ describe("FindView", () => { findView.findEditor.setText("item"); atom.commands.dispatch(findView.findEditor.element, "core:confirm"); expect(findView.refs.replaceAllButton).not.toHaveClass("disabled"); + expect(findView.refs.replacePrevButton).not.toHaveClass("disabled"); expect(findView.refs.replaceNextButton).not.toHaveClass("disabled"); const disposable = findView.replaceTooltipSubscriptions; @@ -479,23 +480,27 @@ describe("FindView", () => { findView.findEditor.setText("it"); atom.commands.dispatch(findView.findEditor.element, "core:confirm"); expect(findView.refs.replaceAllButton).not.toHaveClass("disabled"); + expect(findView.refs.replacePrevButton).not.toHaveClass("disabled"); expect(findView.refs.replaceNextButton).not.toHaveClass("disabled"); expect(disposable.dispose).not.toHaveBeenCalled(); findView.findEditor.setText("nopenotinthefile"); atom.commands.dispatch(findView.findEditor.element, "core:confirm"); expect(findView.refs.replaceAllButton).toHaveClass("disabled"); + expect(findView.refs.replacePrevButton).toHaveClass("disabled"); expect(findView.refs.replaceNextButton).toHaveClass("disabled"); expect(disposable.dispose).toHaveBeenCalled(); findView.findEditor.setText("i"); atom.commands.dispatch(findView.findEditor.element, "core:confirm"); expect(findView.refs.replaceAllButton).not.toHaveClass("disabled"); + expect(findView.refs.replacePrevButton).not.toHaveClass("disabled"); expect(findView.refs.replaceNextButton).not.toHaveClass("disabled"); findView.findEditor.setText(""); atom.commands.dispatch(findView.findEditor.element, "core:confirm"); expect(findView.refs.replaceAllButton).toHaveClass("disabled"); + expect(findView.refs.replacePrevButton).toHaveClass("disabled"); expect(findView.refs.replaceNextButton).toHaveClass("disabled"); }); }); @@ -583,21 +588,18 @@ describe("FindView", () => { expect(findView.findEditor.element).toHaveFocus(); }); + it("selects the previous match when the previous match button is pressed", () => { + findView.refs.prevButton.click(); + expect(findView.refs.resultCounter.textContent).toEqual("1 of 6"); + expect(editor.getSelectedBufferRange()).toEqual([[1, 22], [1, 27]]); + }); + it("selects the next match when the next match button is pressed", () => { findView.refs.nextButton.click(); expect(findView.refs.resultCounter.textContent).toEqual("3 of 6"); expect(editor.getSelectedBufferRange()).toEqual([[2, 34], [2, 39]]); }); - it("selects the previous match when the next match button is pressed while holding shift", () => { - findView.refs.nextButton.dispatchEvent(new MouseEvent("click", { - shiftKey: true - })); - - expect(findView.refs.resultCounter.textContent).toEqual("1 of 6"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 22], [1, 27]]); - }); - it("selects the next match when the 'find-and-replace:find-next' event is triggered and correctly focuses the editor", () => { expect(findView.element).toHaveFocus(); atom.commands.dispatch(editorView, "find-and-replace:find-next"); @@ -1559,6 +1561,16 @@ describe("FindView", () => { }); }); + describe("when the replace previous button is pressed", () => { + it("replaces the match after the cursor and selects the previous match", () => { + findView.refs.replacePrevButton.click(); + expect(findView.refs.resultCounter.textContent).toEqual("5 of 5"); + expect(editor.lineTextForBufferRow(2)).toBe(" if (items.length <= 1) return items;"); + expect(editor.getSelectedBufferRange()).toEqual([[5, 16], [5, 21]]); + expect(findView.replaceEditor.element).toHaveFocus(); + }); + }); + describe("when the replace next button is pressed", () => { it("replaces the match after the cursor and selects the next match", () => { findView.refs.replaceNextButton.click();