-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Language switcher: connect to prefs & clean up some code #8444
Changes from all commits
cc47043
2f542eb
6e6c618
23a3e91
ba1427c
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 |
|---|---|---|
|
|
@@ -38,8 +38,10 @@ define(function (require, exports, module) { | |
| DropdownButton = require("widgets/DropdownButton").DropdownButton, | ||
| EditorManager = require("editor/EditorManager"), | ||
| Editor = require("editor/Editor").Editor, | ||
| FileUtils = require("file/FileUtils"), | ||
| KeyEvent = require("utils/KeyEvent"), | ||
| LanguageManager = require("language/LanguageManager"), | ||
| PreferencesManager = require("preferences/PreferencesManager"), | ||
| StatusBar = require("widgets/StatusBar"), | ||
| Strings = require("strings"), | ||
| StringUtils = require("utils/StringUtils"); | ||
|
|
@@ -53,6 +55,9 @@ define(function (require, exports, module) { | |
| $indentWidthInput, | ||
| $statusOverwrite; | ||
|
|
||
| /** Special list item for the 'set as default' gesture in language switcher dropdown */ | ||
| var LANGUAGE_SET_AS_DEFAULT = {}; | ||
|
|
||
|
|
||
| /** | ||
| * Determine string based on count | ||
|
|
@@ -300,6 +305,9 @@ define(function (require, exports, module) { | |
|
|
||
| languageSelect.items = languages; | ||
|
|
||
| // Add option to top of menu for persisting the override | ||
| languageSelect.items.unshift("---"); | ||
| languageSelect.items.unshift(LANGUAGE_SET_AS_DEFAULT); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -316,8 +324,14 @@ define(function (require, exports, module) { | |
|
|
||
| languageSelect = new DropdownButton("", [], function (item, index) { | ||
| var document = EditorManager.getActiveEditor().document, | ||
| defaultLang = LanguageManager.getLanguageForPath(document.file.fullPath, true), | ||
| html = _.escape(item.getName()); | ||
| defaultLang = LanguageManager.getLanguageForPath(document.file.fullPath, true); | ||
|
|
||
| if (item === LANGUAGE_SET_AS_DEFAULT) { | ||
| var label = _.escape(StringUtils.format(Strings.STATUSBAR_SET_DEFAULT_LANG, FileUtils.getSmartFileExtension(document.file.fullPath))); | ||
| return { html: label, enabled: document.getLanguage() !== defaultLang }; | ||
| } | ||
|
|
||
| var html = _.escape(item.getName()); | ||
|
|
||
| // Show indicators for currently selected & default languages for the current file | ||
| if (item === defaultLang) { | ||
|
|
@@ -361,13 +375,22 @@ define(function (require, exports, module) { | |
| $indentWidthInput.focus(function () { $indentWidthInput.select(); }); | ||
|
|
||
| // Language select change handler | ||
| $(languageSelect).on("select", function (e, lang, index) { | ||
| $(languageSelect).on("select", function (e, lang) { | ||
| var document = EditorManager.getActiveEditor().document, | ||
| fullPath = document.file.fullPath, | ||
| defaultLang = LanguageManager.getLanguageForPath(fullPath, true); | ||
| // if default language selected, don't "force" it | ||
| // (passing in null will reset the force flag) | ||
| document.setLanguageOverride(lang === defaultLang ? null : lang); | ||
| fullPath = document.file.fullPath; | ||
|
|
||
| if (lang === LANGUAGE_SET_AS_DEFAULT) { | ||
| // Set file's current language in preferences as a file extension override (only enabled if not default already) | ||
| var fileExtensionMap = PreferencesManager.get("language.fileExtensions"); | ||
|
Contributor
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 is why I can't get this to work for me. You need to handle Uncaught TypeError: Cannot set property 'jst' of undefined EditorStatusBar.js:385
Member
Author
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. Yikes, good catch indeed, @dangoor The docs for LanguageManager.definePreference() make it appear as if the
Contributor
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. You're right. What LanguageManager does is less than ideal because var newMapping = PreferencesManager.get(pref) || {},rather than just having a default set via |
||
| fileExtensionMap[FileUtils.getSmartFileExtension(fullPath)] = document.getLanguage().getId(); | ||
| PreferencesManager.set("language.fileExtensions", fileExtensionMap); | ||
|
Contributor
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. "language.fileExtensions" was a declared constant
Contributor
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. or actually, why isn't this functionality just an API on language manager?
Member
Author
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 guess that's an interesting architecture philosophy question here (CC @dangoor :-) ...should prefs be considered an encapsulated, private detail of a module (hidden behind programmatic APIs)? Or are they a public API in themselves, since any user can touch them too? Personally, I'd lean toward the latter. Preferences have to be treated much like a frozen API, because we document them publicly and we need backwards compatibility with existing user .json files. Also, prefs definers need to listen to changes in the underlying prefs since users can edit the file at any time -- and making programmatic changes all go through an API might subtly encourage forgetting to handle the external-change case properly.
Contributor
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. that sounds reasonable. It's just interesting the design of languageManger encapsulates so much of the language management features -- even the prefs seem to be defined for internal use only. The constants are even declared as "private" as if we shouldn't use them outside of the module.
Member
Author
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 semi-private consts LanguageManager uses for those two prefs keys do seem a little odd -- almost everywhere else, our code just uses string literals...
Contributor
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. Yeah, this makes sense philosophically: prefs are fundamentally public. I vaguely remember creating some pref or view state value that had a leading underscore, but otherwise they are values that need to have some level of compatibility guarantee just like a public API. |
||
|
|
||
| } else { | ||
| // Set selected language as a path override for just this one file (not persisted) | ||
| var defaultLang = LanguageManager.getLanguageForPath(fullPath, true); | ||
| // if default language selected, pass null to clear the override | ||
| LanguageManager.setLanguageOverrideForPath(fullPath, lang === defaultLang ? null : lang); | ||
| } | ||
| }); | ||
|
|
||
| $statusOverwrite.on("click", _updateEditorOverwriteMode); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -563,8 +563,8 @@ define(function (require, exports, module) { | |
| * When the editor is changed, reset the hinting session and cached | ||
| * information, and reject any pending deferred requests. | ||
| * | ||
| * @param {Editor} editor - editor context to be initialized. | ||
| * @param {Editor} previousEditor - the previous editor. | ||
| * @param {!Editor} editor - editor context to be initialized. | ||
| * @param {?Editor} previousEditor - the previous editor. | ||
| */ | ||
| function initializeSession(editor, previousEditor) { | ||
| session = new Session(editor); | ||
|
|
@@ -575,11 +575,11 @@ define(function (require, exports, module) { | |
| } | ||
|
|
||
| /* | ||
| * Install editor change listeners | ||
| * Connects to the given editor, creating a new Session & adding listeners | ||
| * | ||
| * @param {Editor} editor - editor context on which to listen for | ||
| * changes | ||
| * @param {Editor} previousEditor - the previous editor | ||
| * @param {?Editor} editor - editor context on which to listen for | ||
| * changes. If null, 'session' is cleared. | ||
| * @param {?Editor} previousEditor - the previous editor | ||
| */ | ||
| function installEditorListeners(editor, previousEditor) { | ||
| // always clean up cached scope and hint info | ||
|
|
@@ -624,18 +624,21 @@ define(function (require, exports, module) { | |
| * @param {Editor} previous - the previous editor context | ||
| */ | ||
| function handleActiveEditorChange(event, current, previous) { | ||
| // Uninstall "languageChanged" event listeners on the previous editor's document | ||
| if (previous && previous !== current) { | ||
| // Uninstall "languageChanged" event listeners on previous editor's document & put them on current editor's doc | ||
| if (previous) { | ||
|
Member
Author
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.
|
||
| $(previous.document) | ||
| .off(HintUtils.eventName("languageChanged")); | ||
| } | ||
| if (current && current.document !== DocumentManager.getCurrentDocument()) { | ||
| if (current) { | ||
|
Member
Author
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. Removing the second check here is what allows us to remove the |
||
| $(current.document) | ||
| .on(HintUtils.eventName("languageChanged"), function () { | ||
| // If current doc's language changed, reset our state by treating it as if the user switched to a | ||
| // different document altogether | ||
| uninstallEditorListeners(current); | ||
| installEditorListeners(current); | ||
| }); | ||
| } | ||
|
|
||
| uninstallEditorListeners(previous); | ||
| installEditorListeners(current, previous); | ||
| } | ||
|
|
@@ -803,13 +806,6 @@ define(function (require, exports, module) { | |
| .on(HintUtils.eventName("activeEditorChange"), | ||
| handleActiveEditorChange); | ||
|
|
||
| $(DocumentManager) | ||
| .on("currentDocumentLanguageChanged", function (e) { | ||
| var activeEditor = EditorManager.getActiveEditor(); | ||
| uninstallEditorListeners(activeEditor); | ||
| installEditorListeners(activeEditor); | ||
| }); | ||
|
|
||
| $(ProjectManager).on("beforeProjectClose", function () { | ||
| ScopeManager.handleProjectClose(); | ||
| }); | ||
|
|
||
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.
The original Language Switcher pr went through and we didn't update the events in Document.js -- specifically the
LanguageChangedevent (which is a past-tense event name and we normally use current-tense event names)Actually it appears that there are NO events documented for document objects for some reason. is there a reason why we aren't documenting them? Are they documented somewhere else? I couldn't find them documented anywhere.
We also should notify lint extension authors that they should update their extensions to listen to the "languageChanged" event since most of them leave cruft behind after changing the language of a javascript file to "text". We might want to change it to "languageChange" to match the rest of the events if no one is using it yet as well.
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.
The
"languageChanged"event was added much earlier than the 0.42 language switcher PR -- it dates back to Sprint 21 (c00bfb1), so I'd rather not change it as part of this diff.There are some events documented for Document (see docs on the constructor at the top of Document.js), but not this one. I'll add it.