-
Notifications
You must be signed in to change notification settings - Fork 7.6k
[replace-across-files] Replace in Files #7809
Changes from 51 commits
2ca021e
b60ba25
eaa4d38
32ea44f
5971e7e
d70b40f
b5aa82d
ad367bf
094a75d
0dd3eca
b170527
3e113db
51dda43
8ad4acd
ba02433
cda467a
660fddb
f804242
c2826a1
79a873a
39a9bed
8e0e518
bb6ab8a
f820a12
d571a6f
c33add6
aeca946
6141347
ab95c67
59e39ab
7a9af00
28207e2
5b5d760
72b7121
4a4c9ca
abfd249
8c0c59b
ced86cf
5e6a35d
ea51cc3
ffc5ffb
37ac1b0
c9e4b56
770a389
268cfd8
47fbda5
2778827
2e62bcd
ac10ba2
6e9f6ec
1917878
6490a03
b20b2ee
20876e4
737b27a
f6d3efc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -78,7 +78,7 @@ define(function (require, exports, module) { | |
|
||
this.file = file; | ||
this._updateLanguage(); | ||
this.refreshText(rawText, initialTimestamp); | ||
this.refreshText(rawText, initialTimestamp, true); | ||
} | ||
|
||
/** | ||
|
@@ -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 | ||
|
@@ -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]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this pair of calls occurs in two places now, should be centralize it into a helper function? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. Also fixed up the case in |
||
} | ||
} | ||
this._updateTimestamp(newTimestamp); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we specify that this also suppresses the user-visible UI? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, it seems like that's the only part of the change that's actually required -- we could have it still headlessly reject the Promise. Maybe that would be more generally useful? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the case where we pass true for this, we really don't want to hear about the rejection anyway, because we're just closing the file. So we would have to convert the reject into a resolve in that case anyway, complicating the logic in the caller. |
||
* @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) | ||
|
@@ -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(); | ||
|
@@ -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 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change is also part of making sure that we get |
||
// 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); | ||
} | ||
} | ||
}); | ||
|
@@ -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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The changes here are just a convenience for unit tests (similar to the |
||
var result = new $.Deferred(), | ||
unsavedDocs = []; | ||
|
||
|
@@ -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) { | ||
|
@@ -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)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. StringUtils seems like an odd place for something relatively specific like this. FileUtils is where other file IO error dialog stuff lives... or it could become a Mustache template, I guess... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FileUtils doesn't really seem right, since those are really about file operations. I'll create a DialogUtils module to put it in. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I see what you mean about the error dialog stuff. I can put it in FileUtils. |
||
|
||
Dialogs.showModalDialog( | ||
DefaultDialogs.DIALOG_ID_SAVE_CLOSE, | ||
|
@@ -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 () { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should add to JSDocs above There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. |
||
if (!DocumentManager.getCurrentDocument()) { | ||
EditorManager._closeCustomViewer(); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently, this block of info about There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pretty sure we have many methods where Does moving the "A promise that..." part onto the same line as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Has nothing to do with I just noticed that the entire FYI, by installing apify and then brackets-apify extension, you can quickly render a temporary version of API Docs to see what your annotations look like before submitting PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just remembered a bug recently fixed by @jbalsas where There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK - so sounds like I don't need to change this then? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @njx I opened an issue: jbalsas/apify#69 |
||
*/ | ||
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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This stuff seems use-case-specific enough that I wonder if the Replace code should just call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We want to get the document text if it's already open, though. I don't want to duplicate all the functionality in this method. Plus, I imagine that we could easily have other batch-processing functionality in the future that wants to do something similar across files, where it wants the document text if it's in memory but on-disk text with line ending information if it's on disk. |
||
contents = DocumentModule.Document.normalizeText(contents); | ||
result.resolve(contents); | ||
result.resolve(contents, stat.mtime, originalLineEndings); | ||
} | ||
}); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: This Param doesn't exists and the other 2 have the wrong names. Should it explain better how it compares the paths since is not as simple and comparing just the strings? It splits the paths into the directories and file, and it then compares the nth-part of each path. If those are the same it passes to the next one, if one is a directory, that one goes first. If both are directories, it compares the names. And if both are filenames it uses the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
* @return {number} The result of the local compare function | ||
*/ | ||
function comparePaths(path1, path2) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was hoisted out of the FindInFiles code, since it seemed generally useful (not specific to FindInFiles) and at one point I thought I needed it in multiple places. (Not sure if that's still true, but it seems like a good thing to have available.) |
||
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; | ||
|
@@ -465,4 +497,5 @@ define(function (require, exports, module) { | |
exports.getFileExtension = getFileExtension; | ||
exports.getSmartFileExtension = getSmartFileExtension; | ||
exports.compareFilenames = compareFilenames; | ||
exports.comparePaths = comparePaths; | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,31 @@ | ||
<div id="find-group"><!-- | ||
--><div class="search-input-container"><input type="text" id="find-what" placeholder="{{queryPlaceholder}}" value="{{initialQuery}}" /><div class="error"></div><span id="find-counter"></span></div><!-- | ||
--><button id="find-case-sensitive" class="btn no-focus" tabindex="-1" title="{{Strings.BUTTON_CASESENSITIVE_HINT}}"><div class="button-icon"></div></button><!-- | ||
--><button id="find-regexp" class="btn no-focus" tabindex="-1" title="{{Strings.BUTTON_REGEXP_HINT}}"><div class="button-icon"></div></button><!-- | ||
{{#navigator}} | ||
--><div class="navigator"><!-- | ||
--><button id="find-prev" class="btn no-focus" tabindex="-1" title="{{Strings.BUTTON_PREV_HINT}}">{{Strings.BUTTON_PREV}}</button><!-- | ||
--><button id="find-next" class="btn no-focus" tabindex="-1" title="{{Strings.BUTTON_NEXT_HINT}}">{{Strings.BUTTON_NEXT}}</button><!-- | ||
--></div><!-- | ||
{{/navigator}} | ||
--> | ||
<div class="find-input-group"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The DOM structure here changed slightly since the original unification so that I could make the scope controls There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't quite like how the Replace in Files bar has usually 2 lines, but the fix I am thinking requires the multiple exclusions select. My idea is to make the Exclusions select take the exact same space as the navigation, since Find/Replace have navigation only and Find/Replace in Files have only exclusions. The other thing to fix is the scope that can take a lots of space. I was thinking of just placing the current folder / in project text inside There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @TomMalbran We'll have Exclusions on Find/Replace soon. I agree that the controls should all be on 1 line if there is enough horizontal width for it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is already in master, so we can apply this fix by making the exclusions sets select have always a fixed width that is the exact same width as the prev and next buttons combined. And if we then move the scope to another place, the Replace in Files bar can have the exact same width as the Replace bar which does look nice. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @TomMalbran It seems like we couldn't really shrink down the exclusion-picker dropdown to the tiny width that the next+prev buttons currently occupy, though. (And it seems like you'd have to fit the scope label in that amount of space too, which would be basically impossible even if you change it to only show the last folder name). And if we didn't shrink that set of UI way down, then the problem remains that there's not enough width to reliably fit it, thus it needs to remain wrappable. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had tried that and it looks funny too. Basically, there isn't really a good solution that doesn't leave an awkward set of whitespace somewhere (without doing something more radical). For now, if we're just going to keep all the controls in the bar, it seemed better to just have the fields line up vertically. It would be nice to find a more compact solution eventually. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It did look good to me with that change, and I didn't got any space. But I only tried the solution in the dev tools and I changed the replace group to be inline-block so that it was placed after the exceptions button. I also changed the exceptions text + edit button with the new button, since this branch doesn't have the new exclusions sets. I don't like how it looks right now. Even just Find in Files looks kind of bad with the scope in between the find group and the exclusions set. Maybe the scope can later become a select button, so that you can change the scope after opening the find bar. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I didn't try just having the scope in the second line. But having the exclusions in the top line with everything else seems like it might get crowded too. I'll try to fiddle with it a bit if I get time, but if not, maybe you can put up a PR with your suggestion for @larz0 to review after this lands. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. Notice that I am using the new exclusions button, since is a lot cleaner for the UI and I gave it a fixed width, since right now the width changes depending on the name of the exclusion set and it can potentially take a lot of space. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fwiw, I also like the idea of putting the find+replace on one line and the scope+exclusions on the second line... I think it would read a little more cleanly than the layout today. Not urgent though -- something we could tweak after this all lands in master, or even in a later sprint... |
||
<div id="find-group"><!-- | ||
--><div class="search-input-container"><input type="text" id="find-what" placeholder="{{queryPlaceholder}}" value="{{initialQuery}}" /><div class="error"></div><span id="find-counter"></span></div><!-- | ||
--><button id="find-case-sensitive" class="btn no-focus" tabindex="-1" title="{{Strings.BUTTON_CASESENSITIVE_HINT}}"><div class="button-icon"></div></button><!-- | ||
--><button id="find-regexp" class="btn no-focus" tabindex="-1" title="{{Strings.BUTTON_REGEXP_HINT}}"><div class="button-icon"></div></button><!-- | ||
{{#navigator}} | ||
--><div class="navigator"><!-- | ||
--><button id="find-prev" class="btn no-focus" tabindex="-1" title="{{Strings.BUTTON_PREV_HINT}}">{{Strings.BUTTON_PREV}}</button><!-- | ||
--><button id="find-next" class="btn no-focus" tabindex="-1" title="{{Strings.BUTTON_NEXT_HINT}}">{{Strings.BUTTON_NEXT}}</button><!-- | ||
--></div><!-- | ||
{{/navigator}} | ||
--></div> | ||
|
||
{{#replace}} | ||
<div id="replace-group" {{#scope}}class="has-scope"{{/scope}}><!-- | ||
--><input type="text" id="replace-with" placeholder="{{Strings.REPLACE_PLACEHOLDER}}"/><!-- | ||
{{^replaceAllOnly}} | ||
--><button id="replace-yes" class="btn no-focus" tabindex="-1">{{Strings.BUTTON_REPLACE}}</button><!-- | ||
{{/replaceAllOnly}} | ||
--><button id="replace-all" class="btn no-focus {{#replaceAllOnly}}solo{{/replaceAllOnly}}" tabindex="-1">{{replaceAllLabel}}</button></div> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
{{/replace}} | ||
</div> | ||
|
||
{{#scope}} | ||
<div class="scope-group"> | ||
<div class="no-results-message">{{Strings.FIND_NO_RESULTS}}</div> | ||
<div class="message"> | ||
<span id="searchlabel">{{{scopeLabel}}}</span> | ||
</div> | ||
</div><!-- | ||
|
||
{{#replace}} | ||
--><div id="replace-group"><!-- | ||
--><input type="text" id="replace-with" placeholder="{{Strings.REPLACE_PLACEHOLDER}}"/><!-- | ||
--><button id="replace-yes" class="btn no-focus" tabindex="-1">{{Strings.BUTTON_REPLACE}}</button><!-- | ||
--><button id="replace-all" class="btn no-focus" tabindex="-1">{{Strings.BUTTON_REPLACE_ALL}}</button><!-- | ||
--></div> | ||
{{/replace}} | ||
</div> | ||
{{/scope}} |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change was to make it so we get a
documentChange
event from the global Document module consistently on reverts, even if there is no masterEditor (this is used by FindInFiles to know when a document has changed). However, we don't want to get such an event when the Document is first created, because that's not really a "change".