Skip to content
This repository was archived by the owner on Sep 6, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
2ca021e
Refactors the search results to be able to use paging in Replace All
TomMalbran Mar 3, 2014
8317f0d
Unify FindReplace and FindInFiles modal-bar templates. Get rid of som…
Apr 29, 2014
f240602
Refactor find bar code out of FindReplace and FindInFiles and unify i…
Apr 30, 2014
3f0076e
Reinstate scope label that was erroneously removed from earlier refac…
Apr 30, 2014
1f1e8a5
Store query info in state instead of looking up in preferences
Apr 30, 2014
442676c
Reinstate proper logic for hitting Replace when only Find is open
Apr 30, 2014
b60ba25
Make regexp searches multiline in FindInFiles to match single-file be…
Apr 30, 2014
eaa4d38
Merge with Master
TomMalbran May 2, 2014
32ea44f
Several fixes and stuff
TomMalbran May 2, 2014
5971e7e
Implement basic textual find/replace in files
Apr 30, 2014
d70b40f
Don't replace on disk if the file has changed since we searched it
May 6, 2014
b5aa82d
Add test for gracefully handling write failure
May 6, 2014
ad367bf
Do replacements in memory for files that are already open
May 6, 2014
094a75d
Add way to force replacements to be done in memory instead of on disk
May 6, 2014
0dd3eca
Handle regexp replacement
May 7, 2014
b170527
Start hooking up Replace in Files UI
May 7, 2014
3e113db
Tweak Find Bar to only show Replace All... and relayout in replace-ac…
May 7, 2014
51dda43
Add logic to force in-memory replacements for 10 or fewer files, and …
May 8, 2014
8ad4acd
Add simple unit test for Replace All checkboxes
May 8, 2014
ba02433
Add unit tests for paging Find in Files results
May 8, 2014
cda467a
Merge from tom/search-results
May 8, 2014
660fddb
Use batchOperation() instead of edit op merging for replace all
May 8, 2014
f804242
Integrate results panel with Replace in Files
May 9, 2014
c2826a1
Remove search panel templates that are no longer used
May 9, 2014
79a873a
Improve Enter key behavior in Replace in Files
May 9, 2014
39a9bed
Tweak labels for batch replace buttons in both single and multi-file …
May 9, 2014
8e0e518
Tweak layout of Find bar for find/replace across files
May 9, 2014
bb6ab8a
Disable Replace button when query is blank or invalid
May 9, 2014
f820a12
Automatically open a changed file if current editor hasn't been chang…
May 9, 2014
d571a6f
Use original line endings when comparing in-memory doc to known goods…
May 9, 2014
c33add6
Bump up in-memory replace limit to 20. Tweak dialog to show the limit.
May 10, 2014
aeca946
Ignore unchecked matches when computing number of files to replace in…
May 10, 2014
6141347
Beginning of refactoring to unify view code:
May 10, 2014
ab95c67
Rename resultsModel to searchModel since it has other stuff besides r…
May 10, 2014
59e39ab
Clean up some global state in FindInFiles that can just use the searc…
May 10, 2014
7a9af00
Just reverse the matches instead of sorting them in reverse since the…
May 10, 2014
28207e2
Fix summary display
May 10, 2014
5b5d760
Remove unused var
May 10, 2014
72b7121
Make single-file Replace All just use Find in Files. Plus fixes:
May 12, 2014
4a4c9ca
Move the rest of the query-related globals into SearchModel
May 12, 2014
abfd249
Refactor all UI code out of FindInFiles - this is now a pure engine c…
May 13, 2014
4ea5ce4
Merge branch 'master' into nj/unify-find-ui
May 13, 2014
c7651e7
Merge remote-tracking branch 'origin/master' into nj/unify-find-ui
May 13, 2014
8c0c59b
Merge branch 'nj/unify-find-ui' into nj/replace-on-disk
May 13, 2014
ced86cf
Re-add error log statement that got dropped
May 13, 2014
5e6a35d
Cleanup and bugfixes for Replace in Files:
May 14, 2014
ea51cc3
Make limit on found results much larger, and apply it to total number…
May 14, 2014
ffc5ffb
Move FindInFiles tests into a separate file
May 14, 2014
37ac1b0
Remove unused parameter
May 14, 2014
c9e4b56
Add error dialog if problems occur during replace. Add a few more uni…
May 14, 2014
770a389
Added tests for panel closure. Need to fix a bug that causes one of t…
May 15, 2014
268cfd8
Fixed bug in panel title. Simplified construction of summary area.
May 15, 2014
47fbda5
Tweak flaky unit test - seems to pass consistently now
May 15, 2014
2778827
Add unit test for find/replace in dirty document.
May 15, 2014
2e62bcd
More Replace in Files unit test work:
May 16, 2014
ac10ba2
Ensure that Find in Files panel closes when document is reverted on c…
May 16, 2014
6e9f6ec
Directly include FindInFilesUI instead of FindInFiles, since the form…
May 16, 2014
1917878
Make sure we propagate error from then()
May 16, 2014
6490a03
add Replace in... to context menu
redmunds Jun 3, 2014
b20b2ee
unit tests for replace in...
redmunds Jun 3, 2014
20876e4
update comments
redmunds Jun 3, 2014
737b27a
Replace in Selected File/Folder in Find menu
redmunds Jun 4, 2014
f6d3efc
Merge pull request #8029 from adobe/randy/replace-in
Jun 13, 2014
11c5a93
Merge pull request #7809 from adobe/nj/replace-on-disk
Jun 13, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/base-config/keyboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@
"cmd.findInFiles": [
"Ctrl-Shift-F"
],
"cmd.replaceInFiles": [
"Ctrl-Alt-Shift-F"
],
"cmd.findNext": [
{
"key": "F3"
Expand Down
6 changes: 5 additions & 1 deletion src/brackets.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ define(function (require, exports, module) {
require("editor/EditorCommandHandlers");
require("editor/EditorOptionHandlers");
require("help/HelpCommandHandlers");
require("search/FindInFiles");
require("search/FindInFilesUI");
require("search/FindReplace");
require("extensibility/InstallExtensionDialog");
require("extensibility/ExtensionManagerDialog");
Expand Down Expand Up @@ -161,16 +161,20 @@ define(function (require, exports, module) {
Dialogs : Dialogs,
DocumentCommandHandlers : DocumentCommandHandlers,
DocumentManager : DocumentManager,
DocumentModule : require("document/Document"),
DOMAgent : require("LiveDevelopment/Agents/DOMAgent"),
DragAndDrop : DragAndDrop,
EditorManager : EditorManager,
ExtensionLoader : ExtensionLoader,
ExtensionUtils : ExtensionUtils,
File : require("filesystem/File"),
FileFilters : require("search/FileFilters"),
FileSyncManager : FileSyncManager,
FileSystem : FileSystem,
FileViewController : FileViewController,
FileUtils : require("file/FileUtils"),
FindInFiles : require("search/FindInFiles"),
FindInFilesUI : require("search/FindInFilesUI"),
HTMLInstrumentation : require("language/HTMLInstrumentation"),
Inspector : require("LiveDevelopment/Inspector/Inspector"),
InstallExtensionDialog : require("extensibility/InstallExtensionDialog"),
Expand Down
9 changes: 6 additions & 3 deletions src/command/Commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,18 @@ define(function (require, exports, module) {

// FIND
exports.CMD_FIND = "cmd.find"; // FindReplace.js _launchFind()
exports.CMD_FIND_IN_FILES = "cmd.findInFiles"; // FindInFiles.js _doFindInFiles()
exports.CMD_FIND_IN_SELECTED = "cmd.findInSelected"; // FindInFiles.js _doFindInSubtree()
exports.CMD_FIND_IN_SUBTREE = "cmd.findInSubtree"; // FindInFiles.js _doFindInSubtree()
exports.CMD_FIND_IN_FILES = "cmd.findInFiles"; // FindInFilesUI.js _showFindBar()
exports.CMD_FIND_IN_SELECTED = "cmd.findInSelected"; // FindInFilesUI.js _showFindBarForSubtree()
exports.CMD_FIND_IN_SUBTREE = "cmd.findInSubtree"; // FindInFilesUI.js _showFindBarForSubtree()
exports.CMD_FIND_NEXT = "cmd.findNext"; // FindReplace.js _findNext()
exports.CMD_FIND_PREVIOUS = "cmd.findPrevious"; // FindReplace.js _findPrevious()
exports.CMD_FIND_ALL_AND_SELECT = "cmd.findAllAndSelect"; // FindReplace.js _findAllAndSelect()
exports.CMD_ADD_NEXT_MATCH = "cmd.addNextMatch"; // FindReplace.js _expandAndAddNextToSelection()
exports.CMD_SKIP_CURRENT_MATCH = "cmd.skipCurrentMatch"; // FindReplace.js _skipCurrentMatch()
exports.CMD_REPLACE = "cmd.replace"; // FindReplace.js _replace()
exports.CMD_REPLACE_IN_FILES = "cmd.replaceInFiles"; // FindInFilesUI.js _showReplaceBar()
exports.CMD_REPLACE_IN_SELECTED = "cmd.replaceInSelected"; // FindInFilesUI.js _showReplaceBarForSubtree()
exports.CMD_REPLACE_IN_SUBTREE = "cmd.replaceInSubtree"; // FindInFilesUI.js _showReplaceBarForSubtree()

// VIEW
exports.VIEW_HIDE_SIDEBAR = "view.hideSidebar"; // SidebarView.js toggle()
Expand Down
4 changes: 4 additions & 0 deletions src/command/DefaultMenus.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ define(function (require, exports, module) {
menu.addMenuItem(Commands.CMD_FIND_IN_SELECTED);
menu.addMenuDivider();
menu.addMenuItem(Commands.CMD_REPLACE);
menu.addMenuItem(Commands.CMD_REPLACE_IN_FILES);
menu.addMenuItem(Commands.CMD_REPLACE_IN_SELECTED);

/*
* View menu
Expand Down Expand Up @@ -205,6 +207,7 @@ define(function (require, exports, module) {
project_cmenu.addMenuItem(Commands.NAVIGATE_SHOW_IN_OS);
project_cmenu.addMenuDivider();
project_cmenu.addMenuItem(Commands.CMD_FIND_IN_SUBTREE);
project_cmenu.addMenuItem(Commands.CMD_REPLACE_IN_SUBTREE);
project_cmenu.addMenuDivider();
project_cmenu.addMenuItem(Commands.FILE_REFRESH);

Expand All @@ -216,6 +219,7 @@ define(function (require, exports, module) {
working_set_cmenu.addMenuItem(Commands.NAVIGATE_SHOW_IN_OS);
working_set_cmenu.addMenuDivider();
working_set_cmenu.addMenuItem(Commands.CMD_FIND_IN_SUBTREE);
working_set_cmenu.addMenuItem(Commands.CMD_REPLACE_IN_SUBTREE);
working_set_cmenu.addMenuDivider();
working_set_cmenu.addMenuItem(Commands.FILE_CLOSE);

Expand Down
23 changes: 15 additions & 8 deletions src/document/Document.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ define(function (require, exports, module) {

this.file = file;
this._updateLanguage();
this.refreshText(rawText, initialTimestamp);
this.refreshText(rawText, initialTimestamp, true);
}

/**
Expand Down Expand Up @@ -281,8 +281,10 @@ define(function (require, exports, module) {
* the text's line-ending style. CAN be called even if there is no backing editor.
* @param {!string} text The text to replace the contents of the document with.
* @param {!Date} newTimestamp Timestamp of file at the time we read its new contents from disk.
* @param {boolean} initial True if this is the initial load of the document. In that case,
* we don't send change events.
*/
Document.prototype.refreshText = function (text, newTimestamp) {
Document.prototype.refreshText = function (text, newTimestamp, initial) {
var perfTimerName = PerfUtils.markStart("refreshText:\t" + (!this.file || this.file.fullPath));

// If clean, don't transiently mark dirty during refresh
Expand All @@ -294,12 +296,17 @@ define(function (require, exports, module) {
// _handleEditorChange() triggers "change" event for us
} else {
this._text = text;
// We fake a change record here that looks like CodeMirror's text change records, but
// omits "from" and "to", by which we mean the entire text has changed.
// TODO: Dumb to split it here just to join it again in the change handler, but this is
// the CodeMirror change format. Should we document our change format to allow this to
// either be an array of lines or a single string?
$(this).triggerHandler("change", [this, [{text: text.split(/\r?\n/)}]]);

if (!initial) {
// We fake a change record here that looks like CodeMirror's text change records, but
// omits "from" and "to", by which we mean the entire text has changed.
// TODO: Dumb to split it here just to join it again in the change handler, but this is
// the CodeMirror change format. Should we document our change format to allow this to
// either be an array of lines or a single string?
var fakeChangeList = [{text: text.split(/\r?\n/)}];
$(this).triggerHandler("change", [this, fakeChangeList]);
$(exports).triggerHandler("documentChange", [this, fakeChangeList]);
}
}
this._updateTimestamp(newTimestamp);

Expand Down
60 changes: 32 additions & 28 deletions src/document/DocumentCommandHandlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -666,10 +666,13 @@ define(function (require, exports, module) {
* Reverts the Document to the current contents of its file on disk. Discards any unsaved changes
* in the Document.
* @param {Document} doc
* @return {$.Promise} a Promise that's resolved when done, or rejected with a FileSystemError if the
* file cannot be read (after showing an error dialog to the user).
* @param {boolean=} suppressError If true, then a failure to read the file will be ignored and the
* resulting promise will be resolved rather than rejected.
* @return {$.Promise} a Promise that's resolved when done, or (if suppressError is false)
* rejected with a FileSystemError if the file cannot be read (after showing an error
* dialog to the user).
*/
function doRevert(doc) {
function doRevert(doc, suppressError) {
var result = new $.Deferred();

FileUtils.readAsText(doc.file)
Expand All @@ -678,10 +681,14 @@ define(function (require, exports, module) {
result.resolve();
})
.fail(function (error) {
FileUtils.showFileOpenError(error, doc.file.fullPath)
.done(function () {
result.reject(error);
});
if (suppressError) {
result.resolve();
} else {
FileUtils.showFileOpenError(error, doc.file.fullPath)
.done(function () {
result.reject(error);
});
}
});

return result.promise();
Expand Down Expand Up @@ -1070,13 +1077,19 @@ define(function (require, exports, module) {
// copy of whatever's on disk.
doClose(file);

// Only reload from disk if we've executed the Close for real,
// *and* if at least one other view still exists
if (!promptOnly && DocumentManager.getOpenDocumentForPath(file.fullPath)) {
doRevert(doc)
.then(result.resolve, result.reject);
} else {
// Only reload from disk if we've executed the Close for real.
if (promptOnly) {
result.resolve();
} else {
// Even if there are no listeners attached to the document at this point, we want
// to do the revert anyway, because clients who are listening to the global documentChange
// event from the Document module (rather than attaching to the document directly),
// such as the Find in Files panel, should get a change event. However, in that case,
// we want to ignore errors during the revert, since we don't want a failed revert
// to throw a dialog if the document isn't actually open in the UI.
var suppressError = !DocumentManager.getOpenDocumentForPath(file.fullPath);
doRevert(doc, suppressError)
.then(result.resolve, result.reject);
}
}
});
Expand All @@ -1096,8 +1109,9 @@ define(function (require, exports, module) {
* @param {!Array.<FileEntry>} list
* @param {boolean} promptOnly
* @param {boolean} clearCurrentDoc
* @param {boolean} _forceClose Whether to force all the documents to close even if they have unsaved changes. For unit testing only.
*/
function _closeList(list, promptOnly, clearCurrentDoc) {
function _closeList(list, promptOnly, clearCurrentDoc, _forceClose) {
var result = new $.Deferred(),
unsavedDocs = [];

Expand All @@ -1108,8 +1122,8 @@ define(function (require, exports, module) {
}
});

if (unsavedDocs.length === 0) {
// No unsaved changes, so we can proceed without a prompt
if (unsavedDocs.length === 0 || _forceClose) {
// No unsaved changes or we want to ignore them, so we can proceed without a prompt
result.resolve();

} else if (unsavedDocs.length === 1) {
Expand All @@ -1125,17 +1139,7 @@ define(function (require, exports, module) {

} else {
// Multiple unsaved files: show a single bulk prompt listing all files
var message = Strings.SAVE_CLOSE_MULTI_MESSAGE;

message += "<ul class='dialog-list'>";
unsavedDocs.forEach(function (doc) {
var fullPath = doc.file.fullPath;

message += "<li><span class='dialog-filename'>";
message += StringUtils.breakableUrl(_shortTitleForDocument(doc));
message += "</span></li>";
});
message += "</ul>";
var message = Strings.SAVE_CLOSE_MULTI_MESSAGE + StringUtils.makeDialogFileList(_.map(unsavedDocs, _shortTitleForDocument));

Dialogs.showModalDialog(
DefaultDialogs.DIALOG_ID_SAVE_CLOSE,
Expand Down Expand Up @@ -1200,7 +1204,7 @@ define(function (require, exports, module) {
*/
function handleFileCloseAll(commandData) {
return _closeList(DocumentManager.getWorkingSet(),
(commandData && commandData.promptOnly), true).done(function () {
(commandData && commandData.promptOnly), true, (commandData && commandData._forceClose)).done(function () {
if (!DocumentManager.getCurrentDocument()) {
EditorManager._closeCustomViewer();
}
Expand Down
20 changes: 14 additions & 6 deletions src/document/DocumentManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -735,23 +735,31 @@ define(function (require, exports, module) {
* Differs from plain FileUtils.readAsText() in two ways: (a) line endings are still normalized
* as in Document.getText(); (b) unsaved changes are returned if there are any.
*
* @param {!File} file
* @return {!string}
* @param {!File} file The file to get the text for.
* @param {boolean=} checkLineEndings Whether to return line ending information. Default false (slightly more efficient).
* @return {$.Promise}
* A promise that is resolved with three parameters:
* contents - string: the document's text
* timestamp - Date: the last time the document was changed on disk (might not be the same as the last time it was changed in memory)
* lineEndings - string: the original line endings of the file, one of the FileUtils.LINE_ENDINGS_* constants;
* will be null if checkLineEndings was false.
* or rejected with a filesystem error.
*/
function getDocumentText(file) {
function getDocumentText(file, checkLineEndings) {
var result = new $.Deferred(),
doc = getOpenDocumentForPath(file.fullPath);
if (doc) {
result.resolve(doc.getText());
result.resolve(doc.getText(), doc.diskTimestamp, checkLineEndings ? doc._lineEndings : null);
} else {
file.read(function (err, contents) {
file.read(function (err, contents, stat) {
if (err) {
result.reject(err);
} else {
// Normalize line endings the same way Document would, but don't actually
// new up a Document (which entails a bunch of object churn).
var originalLineEndings = checkLineEndings ? FileUtils.sniffLineEndings(contents) : null;
contents = DocumentModule.Document.normalizeText(contents);
result.resolve(contents);
result.resolve(contents, stat.mtime, originalLineEndings);
}
});
}
Expand Down
33 changes: 33 additions & 0 deletions src/file/FileUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,39 @@ define(function (require, exports, module) {

return extFirst ? (cmpExt || cmpNames) : (cmpNames || cmpExt);
}

/**
* Compares two paths. Useful for sorting.
* @param {string} filename1
* @param {string} filename2
* @param {boolean} extFirst If true it compares the extensions first and then the file names.
* @return {number} The result of the local compare function
*/
function comparePaths(path1, path2) {
var entryName1, entryName2,
pathParts1 = path1.split("/"),
pathParts2 = path2.split("/"),
length = Math.min(pathParts1.length, pathParts2.length),
folders1 = pathParts1.length - 1,
folders2 = pathParts2.length - 1,
index = 0;

while (index < length) {
entryName1 = pathParts1[index];
entryName2 = pathParts2[index];

if (entryName1 !== entryName2) {
if (index < folders1 && index < folders2) {
return entryName1.toLocaleLowerCase().localeCompare(entryName2.toLocaleLowerCase());
} else if (index >= folders1 && index >= folders2) {
return compareFilenames(entryName1, entryName2);
}
return (index >= folders1 && index < folders2) ? 1 : -1;
}
index++;
}
return 0;
}

// Define public API
exports.LINE_ENDINGS_CRLF = LINE_ENDINGS_CRLF;
Expand All @@ -465,4 +497,5 @@ define(function (require, exports, module) {
exports.getFileExtension = getFileExtension;
exports.getSmartFileExtension = getSmartFileExtension;
exports.compareFilenames = compareFilenames;
exports.comparePaths = comparePaths;
});
10 changes: 0 additions & 10 deletions src/htmlContent/findinfiles-bar.html

This file was deleted.

Loading