diff --git a/src/language/LanguageManager.js b/src/language/LanguageManager.js index 5b06397b57f..586b9fcdadc 100644 --- a/src/language/LanguageManager.js +++ b/src/language/LanguageManager.js @@ -466,11 +466,17 @@ define(function (require, exports, module) { }; /** - * Adds a file extension to this language. - * @param {!string} extension A file extension used by this language - * @return {boolean} Whether adding the file extension was successful or not + * Adds one or more file extensions to this language. + * @param {!string|Array.} extension A file extension (or array thereof) used by this language */ Language.prototype.addFileExtension = function (extension) { + if (Array.isArray(extension)) { + extension.forEach(this._addFileExtension.bind(this)); + } else { + this._addFileExtension(extension); + } + }; + Language.prototype._addFileExtension = function (extension) { // Remove a leading dot if present if (extension.charAt(0) === ".") { extension = extension.substr(1); @@ -494,11 +500,47 @@ define(function (require, exports, module) { }; /** - * Adds a file name to the language which is used to match files that don't have extensions like "Makefile" for example. - * @param {!string} extension An extensionless file name used by this language - * @return {boolean} Whether adding the file name was successful or not + * Unregisters one or more file extensions from this language. + * @param {!string|Array.} extension File extension (or array thereof) to stop using for this language + */ + Language.prototype.removeFileExtension = function (extension) { + if (Array.isArray(extension)) { + extension.forEach(this._removeFileExtension.bind(this)); + } else { + this._removeFileExtension(extension); + } + }; + Language.prototype._removeFileExtension = function (extension) { + // Remove a leading dot if present + if (extension.charAt(0) === ".") { + extension = extension.substr(1); + } + + // Make checks below case-INsensitive + extension = extension.toLowerCase(); + + var index = this._fileExtensions.indexOf(extension); + if (index !== -1) { + this._fileExtensions.splice(index, 1); + + delete _fileExtensionToLanguageMap[extension]; + + this._wasModified(); + } + }; + + /** + * Adds one or more file names to the language which is used to match files that don't have extensions like "Makefile" for example. + * @param {!string|Array.} extension An extensionless file name (or array thereof) used by this language */ Language.prototype.addFileName = function (name) { + if (Array.isArray(name)) { + name.forEach(this._addFileName.bind(this)); + } else { + this._addFileName(name); + } + }; + Language.prototype._addFileName = function (name) { // Make checks below case-INsensitive name = name.toLowerCase(); @@ -514,7 +556,31 @@ define(function (require, exports, module) { this._wasModified(); } - return true; + }; + + /** + * Unregisters one or more file names from this language. + * @param {!string|Array.} extension An extensionless file name (or array thereof) used by this language + */ + Language.prototype.removeFileName = function (name) { + if (Array.isArray(name)) { + name.forEach(this._removeFileName.bind(this)); + } else { + this._removeFileName(name); + } + }; + Language.prototype._removeFileName = function (name) { + // Make checks below case-INsensitive + name = name.toLowerCase(); + + var index = this._fileNames.indexOf(name); + if (index !== -1) { + this._fileNames.splice(index, 1); + + delete _fileNameToLanguageMap[name]; + + this._wasModified(); + } }; /** @@ -770,11 +836,11 @@ define(function (require, exports, module) { _patchCodeMirror(); // Define a custom MIME mode here instead of putting it directly into languages.json - // because JSON files must not contain regular expressions. Also, all other modes so + // because JSON files can't contain regular expressions. Also, all other modes so // far were strings, so we spare us the trouble of allowing more complex mode values. CodeMirror.defineMIME("text/x-brackets-html", { "name": "htmlmixed", - "scriptTypes": [{"matches": /\/x-handlebars-template|\/x-mustache/i, + "scriptTypes": [{"matches": /\/x-handlebars|\/x-mustache|^text\/html$/i, "mode": null}] }); @@ -796,6 +862,10 @@ define(function (require, exports, module) { // But for now, we need to associate this madeup "html" mode with our HTML language object. _setLanguageForMode("html", html); + // Similarly, the php mode uses clike internally for the PHP parts + var php = getLanguage("php"); + php._setLanguageForMode("clike", php); + // The fallback language for unknown modes and file extensions _fallbackLanguage = getLanguage("unknown"); }); diff --git a/src/language/languages.json b/src/language/languages.json index d1d17992b16..a229650ee30 100644 --- a/src/language/languages.json +++ b/src/language/languages.json @@ -93,7 +93,9 @@ "php": { "name": "PHP", "mode": "php", - "fileExtensions": ["php", "php3", "php4", "php5", "phtm", "phtml", "ctp"] + "fileExtensions": ["php", "php3", "php4", "php5", "phtm", "phtml", "ctp"], + "blockComment": ["/*", "*/"], + "lineComment": ["//", "#"] }, "c": { @@ -120,13 +122,6 @@ "lineComment": ["//"] }, - "clike": { - "name": "clike", - "mode": "clike", - "blockComment": ["/*", "*/"], - "lineComment": ["//", "#"] - }, - "java": { "name": "Java", "mode": ["clike", "text/x-java"], @@ -138,7 +133,9 @@ "scala": { "name": "Scala", "mode": ["clike", "text/x-scala"], - "fileExtensions": ["scala", "sbt"] + "fileExtensions": ["scala", "sbt"], + "blockComment": ["/*", "*/"], + "lineComment": ["//"] }, "coffeescript": { @@ -242,5 +239,13 @@ "name": "Audio", "fileExtensions": ["mp3", "wav", "aif", "aiff", "ogg"], "isBinary": true + }, + + "binary": { + "name": "Other Binary", + "fileExtensions": ["svgz", "jsz", "zip", "gz", "htmz", "htmlz", "rar", "tar", "exe", "bin", "dll", "pdb", "lib", "obj", "o", "so", "a", "dylib", "node", + "pdf", "psd", "ai", "tif", "tiff", "mpg", "mpeg", "avi", "flv", "mp4", "swf", "ttf", "otf", "woff", "eot", + "doc", "docx", "xls", "xlsx", "ppt", "pptx", "sqlite"], + "isBinary": true } } diff --git a/src/search/FindInFiles.js b/src/search/FindInFiles.js index a40c011f21f..376917419d3 100644 --- a/src/search/FindInFiles.js +++ b/src/search/FindInFiles.js @@ -751,7 +751,9 @@ define(function (require, exports, module) { var inWorkingSet = DocumentManager.getWorkingSet().some(function (wsFile) { return wsFile.fullPath === file.fullPath; }); - return inWorkingSet; + if (!inWorkingSet) { + return false; + } } } // In the initial search, this is passed as a getAllFiles() filter diff --git a/test/spec/LanguageManager-test.js b/test/spec/LanguageManager-test.js index dbc72545277..f66afa8bec1 100644 --- a/test/spec/LanguageManager-test.js +++ b/test/spec/LanguageManager-test.js @@ -181,6 +181,88 @@ define(function (require, exports, module) { expect(LanguageManager.getLanguageForPath("cakefile.doesNotExist")).toBe(unknown); expect(LanguageManager.getLanguageForPath("Something.cakefile")).toBe(unknown); }); + + it("should remove file extensions and add to new languages", function () { + var html = LanguageManager.getLanguage("html"), + ruby = LanguageManager.getLanguage("ruby"), + unknown = LanguageManager.getLanguage("unknown"); + + expect(LanguageManager.getLanguageForPath("test.html")).toBe(html); + + html.removeFileExtension("html"); + expect(LanguageManager.getLanguageForPath("test.html")).toBe(unknown); + + ruby.addFileExtension("html"); + expect(LanguageManager.getLanguageForPath("test.html")).toBe(ruby); + }); + + it("should remove file names and add to new languages", function () { + var coffee = LanguageManager.getLanguage("coffeescript"), + html = LanguageManager.getLanguage("html"), + unknown = LanguageManager.getLanguage("unknown"); + + expect(LanguageManager.getLanguageForPath("Cakefile")).toBe(coffee); + + coffee.removeFileName("Cakefile"); + expect(LanguageManager.getLanguageForPath("Cakefile")).toBe(unknown); + + html.addFileName("Cakefile"); + expect(LanguageManager.getLanguageForPath("Cakefile")).toBe(html); + }); + + it("should add multiple file extensions to languages", function () { + var ruby = LanguageManager.getLanguage("ruby"), + unknown = LanguageManager.getLanguage("unknown"); + + expect(LanguageManager.getLanguageForPath("foo.1")).toBe(unknown); + expect(LanguageManager.getLanguageForPath("foo.2")).toBe(unknown); + + ruby.addFileExtension(["1", "2"]); + + expect(LanguageManager.getLanguageForPath("foo.1")).toBe(ruby); + expect(LanguageManager.getLanguageForPath("foo.2")).toBe(ruby); + }); + + it("should remove multiple file extensions from languages", function () { + var ruby = LanguageManager.getLanguage("ruby"), + unknown = LanguageManager.getLanguage("unknown"); + + // Assumes test above already ran (tests in this suite are not isolated) + expect(LanguageManager.getLanguageForPath("foo.1")).toBe(ruby); + expect(LanguageManager.getLanguageForPath("foo.2")).toBe(ruby); + + ruby.removeFileExtension(["1", "2"]); + + expect(LanguageManager.getLanguageForPath("foo.1")).toBe(unknown); + expect(LanguageManager.getLanguageForPath("foo.2")).toBe(unknown); + }); + + it("should add multiple file names to languages", function () { + var ruby = LanguageManager.getLanguage("ruby"), + unknown = LanguageManager.getLanguage("unknown"); + + expect(LanguageManager.getLanguageForPath("rubyFile1")).toBe(unknown); + expect(LanguageManager.getLanguageForPath("rubyFile2")).toBe(unknown); + + ruby.addFileName(["rubyFile1", "rubyFile2"]); + + expect(LanguageManager.getLanguageForPath("rubyFile1")).toBe(ruby); + expect(LanguageManager.getLanguageForPath("rubyFile2")).toBe(ruby); + }); + + it("should remove multiple file names from languages", function () { + var ruby = LanguageManager.getLanguage("ruby"), + unknown = LanguageManager.getLanguage("unknown"); + + // Assumes test above already ran (tests in this suite are not isolated) + expect(LanguageManager.getLanguageForPath("rubyFile1")).toBe(ruby); + expect(LanguageManager.getLanguageForPath("rubyFile2")).toBe(ruby); + + ruby.removeFileName(["rubyFile1", "rubyFile2"]); + + expect(LanguageManager.getLanguageForPath("rubyFile1")).toBe(unknown); + expect(LanguageManager.getLanguageForPath("rubyFile2")).toBe(unknown); + }); }); describe("defineLanguage", function () {