diff --git a/lib/find.coffee b/lib/find.coffee index c0c8a991..bce263be 100644 --- a/lib/find.coffee +++ b/lib/find.coffee @@ -11,6 +11,11 @@ ProjectFindView = require './project-find-view' ResultsModel = require './project/results-model' ResultsPaneView = require './project/results-pane' +# To convert previous (and now unused) config setting "openProjectFindResultsInRightPane" +if atom.config.get('find-and-replace.openProjectFindResultsInRightPane') + atom.config.set('find-and-replace.openProjectFindResultsDirection', 'right') + atom.config.unset('find-and-replace.openProjectFindResultsInRightPane') + module.exports = activate: ({findOptions, findHistory, replaceHistory, pathsHistory}={}) -> atom.workspace.addOpener (filePath) -> diff --git a/lib/project-find-view.coffee b/lib/project-find-view.coffee index fdfaef5e..70c1c993 100644 --- a/lib/project-find-view.coffee +++ b/lib/project-find-view.coffee @@ -302,7 +302,8 @@ class ProjectFindView extends View showResultPane: -> options = {searchAllPanes: true} - options.split = 'right' if atom.config.get('find-and-replace.openProjectFindResultsInRightPane') + openDirection = atom.config.get('find-and-replace.openProjectFindResultsDirection') + options.split = openDirection unless openDirection is 'none' atom.workspace.open(ResultsPaneView.URI, options) onFinishedReplacing: (results) -> diff --git a/lib/project/match-view.coffee b/lib/project/match-view.coffee index 485b7593..a76fff17 100644 --- a/lib/project/match-view.coffee +++ b/lib/project/match-view.coffee @@ -43,8 +43,13 @@ class MatchView extends View @matchText.removeClass('highlight-error').addClass('highlight-info') confirm: (options = {}) -> - openInRightPane = atom.config.get('find-and-replace.openProjectFindResultsInRightPane') - options.split = 'left' if openInRightPane + reverseDirections = + left: 'right' + right: 'left' + up: 'down' + down: 'up' + openDirection = atom.config.get('find-and-replace.openProjectFindResultsDirection') + options.split = reverseDirections[openDirection] unless openDirection is 'none' editorPromise = atom.workspace.open(@filePath, options) editorPromise.then (editor) => editor.setSelectedBufferRange(@match.range, autoscroll: true) diff --git a/package.json b/package.json index 6f8116dc..c5371e3e 100644 --- a/package.json +++ b/package.json @@ -58,9 +58,11 @@ "default": false, "description": "Focus the editor and select the next match when a file search is executed. If no matches are found, the editor will not be focused." }, - "openProjectFindResultsInRightPane": { - "type": "boolean", - "default": false, + "openProjectFindResultsDirection": { + "type": "string", + "default": "none", + "enum": ["none", "right", "down"], + "title": "Direction to open results pane", "description": "When a project-wide search is executed, open the results in a split pane instead of a tab in the same pane." }, "closeFindPanelAfterSearch": { diff --git a/spec/project-find-view-spec.coffee b/spec/project-find-view-spec.coffee index f9211bbf..8928edfc 100644 --- a/spec/project-find-view-spec.coffee +++ b/spec/project-find-view-spec.coffee @@ -28,7 +28,7 @@ describe 'ProjectFindView', -> atom.project.setPaths([path.join(__dirname, 'fixtures')]) jasmine.attachToDOM(workspaceElement) - atom.config.set('find-and-replace.openProjectFindResultsInRightPane', false) + atom.config.set('find-and-replace.openProjectFindResultsDirection', 'none') activationPromise = atom.packages.activatePackage("find-and-replace").then (options) -> mainModule = options.mainModule mainModule.createViews() @@ -366,9 +366,22 @@ describe 'ProjectFindView', -> workspaceElement.style.height = '1000px' atom.commands.dispatch editorView, 'project-find:show' - it "splits when option is true", -> + it "splits when option is right", -> initialPane = atom.workspace.getActivePane() - atom.config.set('find-and-replace.openProjectFindResultsInRightPane', true) + atom.config.set('find-and-replace.openProjectFindResultsDirection', 'right') + projectFindView.findEditor.setText('items') + atom.commands.dispatch(projectFindView[0], 'core:confirm') + + waitsForPromise -> + searchPromise + + runs -> + pane1 = atom.workspace.getActivePane() + expect(pane1).not.toBe initialPane + + it "splits when option is bottom", -> + initialPane = atom.workspace.getActivePane() + atom.config.set('find-and-replace.openProjectFindResultsDirection', 'down') projectFindView.findEditor.setText('items') atom.commands.dispatch(projectFindView[0], 'core:confirm') @@ -391,8 +404,8 @@ describe 'ProjectFindView', -> pane1 = atom.workspace.getActivePane() expect(pane1).toBe initialPane - it "can be duplicated", -> - atom.config.set('find-and-replace.openProjectFindResultsInRightPane', true) + it "can be duplicated on the right", -> + atom.config.set('find-and-replace.openProjectFindResultsDirection', 'right') projectFindView.findEditor.setText('items') atom.commands.dispatch(projectFindView[0], 'core:confirm') @@ -416,6 +429,31 @@ describe 'ProjectFindView', -> expect(resultsPaneView2.querySelector('.preview-count').innerHTML).toEqual resultsPaneView1.querySelector('.preview-count').innerHTML + it "can be duplicated at the bottom", -> + atom.config.set('find-and-replace.openProjectFindResultsDirection', 'down') + projectFindView.findEditor.setText('items') + atom.commands.dispatch(projectFindView[0], 'core:confirm') + + waitsForPromise -> + searchPromise + + runs -> + resultsPaneView1 = atom.views.getView(getExistingResultsPane()) + pane1 = atom.workspace.getActivePane() + pane1.splitDown(copyActiveItem: true) + + pane2 = atom.workspace.getActivePane() + resultsPaneView2 = atom.views.getView(pane2.itemForURI(ResultsPaneView.URI)) + + expect(pane1).not.toBe pane2 + expect(resultsPaneView1).not.toBe resultsPaneView2 + + length = resultsPaneView1.querySelectorAll('li > ul > li').length + expect(length).toBeGreaterThan 0 + expect(resultsPaneView2.querySelectorAll('li > ul > li')).toHaveLength length + + expect(resultsPaneView2.querySelector('.preview-count').innerHTML).toEqual resultsPaneView1.querySelector('.preview-count').innerHTML + describe "serialization", -> it "serializes if the case, regex and whole word options", -> atom.commands.dispatch editorView, 'project-find:show' @@ -1412,9 +1450,9 @@ describe 'ProjectFindView', -> expect(projectFindView.pathsEditor).not.toHaveClass('is-focused') describe "panel opening", -> - describe "when a panel is already open", -> + describe "when a panel is already open on the right", -> beforeEach -> - atom.config.set('find-and-replace.openProjectFindResultsInRightPane', true) + atom.config.set('find-and-replace.openProjectFindResultsDirection', 'right') waitsForPromise -> atom.workspace.open('sample.js') @@ -1445,6 +1483,39 @@ describe 'ProjectFindView', -> runs -> expect(workspaceElement.querySelectorAll('.preview-pane').length).toBe(1) + describe "when a panel is already open at the bottom", -> + beforeEach -> + atom.config.set('find-and-replace.openProjectFindResultsDirection', 'down') + + waitsForPromise -> + atom.workspace.open('sample.js') + + runs -> + editor = atom.workspace.getActiveTextEditor() + editorView = atom.views.getView(editor) + atom.commands.dispatch(workspaceElement, 'project-find:show') + + waitsForPromise -> + activationPromise + + runs -> + projectFindView.findEditor.setText('items') + atom.commands.dispatch(projectFindView[0], 'core:confirm') + + waitsForPromise -> + searchPromise + + it "doesn't open another panel even if the active pane is horizontally split", -> + atom.commands.dispatch(editorView, 'pane:split-right') + projectFindView.findEditor.setText('items') + atom.commands.dispatch(projectFindView[0], 'core:confirm') + + waitsForPromise -> + searchPromise + + runs -> + expect(workspaceElement.querySelectorAll('.preview-pane').length).toBe(1) + describe "when language-javascript is active", -> beforeEach -> waitsForPromise -> diff --git a/spec/results-view-spec.coffee b/spec/results-view-spec.coffee index ecc4d2ab..1e238e94 100644 --- a/spec/results-view-spec.coffee +++ b/spec/results-view-spec.coffee @@ -441,9 +441,19 @@ describe 'ResultsView', -> runs -> expect(atom.views.getView(editor)).toHaveFocus() - describe "when `openProjectFindResultsInRightPane` option is true", -> + describe "when `openProjectFindResultsDirection` option is none", -> beforeEach -> - atom.config.set('find-and-replace.openProjectFindResultsInRightPane', true) + atom.config.set('find-and-replace.openProjectFindResultsDirection', 'none') + + it "does not specify a pane to split", -> + spyOn(atom.workspace, 'open').andCallThrough() + atom.commands.dispatch resultsView.element, 'core:move-down' + atom.commands.dispatch resultsView.element, 'core:confirm' + expect(atom.workspace.open.mostRecentCall.args[1]).toEqual {} + + describe "when `openProjectFindResultsDirection` option is right", -> + beforeEach -> + atom.config.set('find-and-replace.openProjectFindResultsDirection', 'right') it "always opens the file in the left pane", -> spyOn(atom.workspace, 'open').andCallThrough() @@ -464,15 +474,28 @@ describe 'ResultsView', -> runs -> expect(atom.views.getView(editor)).toHaveFocus() - describe "when `openProjectFindResultsInRightPane` option is false", -> + describe "when `openProjectFindResultsDirection` option is down", -> beforeEach -> - atom.config.set('find-and-replace.openProjectFindResultsInRightPane', false) + atom.config.set('find-and-replace.openProjectFindResultsDirection', 'down') - it "does not specify a pane to split", -> + it "always opens the file in the up pane", -> spyOn(atom.workspace, 'open').andCallThrough() atom.commands.dispatch resultsView.element, 'core:move-down' atom.commands.dispatch resultsView.element, 'core:confirm' - expect(atom.workspace.open.mostRecentCall.args[1]).toEqual {} + expect(atom.workspace.open.mostRecentCall.args[1].split).toBe 'up' + + describe "when a search result is single-clicked", -> + it "opens the file containing the result in pending state", -> + pathNode = resultsView.find(".search-result")[0] + pathNode.dispatchEvent(buildMouseEvent('mousedown', target: pathNode, which: 1)) + editor = null + waitsFor -> + editor = atom.workspace.getActiveTextEditor() + waitsFor -> + atom.workspace.getActivePane().getPendingItem() is editor + + runs -> + expect(atom.views.getView(editor)).toHaveFocus() describe "arrowing through the list", -> it "arrows through the entire list without selecting paths and overshooting the boundaries", ->