From 09d232ba4108c13d350af49abcd325ae113d7289 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 12 Aug 2016 12:21:51 -0700 Subject: [PATCH] Introduce TextEditorRegistry::build This way, we can construct text editors with the right parameters from the start --- spec/text-editor-registry-spec.js | 18 ++++++++++ src/atom-environment.coffee | 4 ++- src/text-editor-registry.js | 56 +++++++++++++++++++++++++------ src/workspace.coffee | 7 ++-- 4 files changed, 68 insertions(+), 17 deletions(-) diff --git a/spec/text-editor-registry-spec.js b/spec/text-editor-registry-spec.js index 7b4d0e283..7181dddf7 100644 --- a/spec/text-editor-registry-spec.js +++ b/spec/text-editor-registry-spec.js @@ -2,6 +2,7 @@ import TextEditorRegistry from '../src/text-editor-registry' import TextEditor from '../src/text-editor' +import TextBuffer from 'text-buffer' import {it, fit, ffit, fffit} from './async-spec-helpers' import dedent from 'dedent' @@ -10,7 +11,9 @@ describe('TextEditorRegistry', function () { beforeEach(function () { registry = new TextEditorRegistry({ + assert: atom.assert, config: atom.config, + clipboard: atom.clipboard, grammarRegistry: atom.grammars }) @@ -61,6 +64,19 @@ describe('TextEditorRegistry', function () { }) }) + describe('.build', function () { + it('constructs a TextEditor with the right parameters based on its path and text', async function () { + await atom.packages.activatePackage('language-javascript') + await atom.packages.activatePackage('language-c') + + atom.config.set('editor.tabLength', 8, {scope: '.source.js'}) + + const editor = registry.build({buffer: new TextBuffer({filePath: 'test.js'})}) + expect(editor.getGrammar().name).toBe("JavaScript") + expect(editor.getTabLength()).toBe(8) + }) + }) + describe('.maintainGrammar', function () { it('assigns a grammar to the editor based on its path', async function () { await atom.packages.activatePackage('language-javascript') @@ -573,7 +589,9 @@ describe('TextEditorRegistry', function () { const editor2Copy = TextEditor.deserialize(editor2.serialize(), atom) const registryCopy = new TextEditorRegistry({ + assert: atom.assert, config: atom.config, + clipboard: atom.clipboard, grammarRegistry: atom.grammars }) registryCopy.deserialize(JSON.parse(JSON.stringify(registry.serialize()))) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index c482e97e9..8ed918643 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -190,7 +190,9 @@ class AtomEnvironment extends Model @commandInstaller = new CommandInstaller(@getVersion(), @applicationDelegate) - @textEditors = new TextEditorRegistry({@config, grammarRegistry: @grammars}) + @textEditors = new TextEditorRegistry({ + @config, grammarRegistry: @grammars, assert: @assert.bind(this), @clipboard + }) @workspace = new Workspace({ @config, @project, packageManager: @packages, grammarRegistry: @grammars, deserializerManager: @deserializers, diff --git a/src/text-editor-registry.js b/src/text-editor-registry.js index 91d645587..c42400432 100644 --- a/src/text-editor-registry.js +++ b/src/text-editor-registry.js @@ -2,7 +2,8 @@ import {Emitter, Disposable, CompositeDisposable} from 'event-kit' import {Point, Range} from 'atom' -import NullGrammar from './null-grammar' +import TextEditor from './text-editor' +import ScopeDescriptor from './scope-descriptor' const EDITOR_PARAMS_BY_SETTING_KEY = [ ['core.fileEncoding', 'encoding'], @@ -38,7 +39,9 @@ const GRAMMAR_SELECTION_RANGE = Range(Point.ZERO, Point(10, 0)).freeze() // done using your editor, be sure to call `dispose` on the returned disposable // to avoid leaking editors. export default class TextEditorRegistry { - constructor ({config, grammarRegistry}) { + constructor ({config, grammarRegistry, clipboard, assert}) { + this.assert = assert + this.clipboard = clipboard this.config = config this.grammarRegistry = grammarRegistry this.scopedSettingsDelegate = new ScopedSettingsDelegate(config) @@ -95,6 +98,25 @@ export default class TextEditorRegistry { return new Disposable(() => this.remove(editor)) } + build (params) { + params = Object.assign({ + clipboard: this.clipboard, + assert: this.assert + }, params) + + let scope = null + if (params.buffer) { + const filePath = params.buffer.getPath() + const headContent = params.buffer.getTextInRange(GRAMMAR_SELECTION_RANGE) + params.grammar = this.grammarRegistry.selectGrammar(filePath, headContent) + scope = new ScopeDescriptor({scopes: [params.grammar.scopeName]}) + } + + Object.assign(params, this.textEditorParamsForScope(scope)) + + return new TextEditor(params) + } + // Remove a `TextEditor`. // // * `editor` The editor to remove. @@ -174,8 +196,16 @@ export default class TextEditorRegistry { } this.editorsWithMaintainedGrammar.add(editor) - if (editor.getGrammar() !== NullGrammar) { - this.editorGrammarOverrides[editor.id] = editor.getGrammar().scopeName + + const buffer = editor.getBuffer() + for (let existingEditor of this.editorsWithMaintainedGrammar) { + if (existingEditor.getBuffer() === buffer) { + const existingOverride = this.editorGrammarOverrides[existingEditor.id] + if (existingOverride) { + this.editorGrammarOverrides[editor.id] = existingOverride + } + break + } } this.selectGrammarForEditor(editor) @@ -285,17 +315,12 @@ export default class TextEditorRegistry { subscribeToSettingsForEditorScope (editor) { const scopeDescriptor = editor.getRootScopeDescriptor() const scopeChain = scopeDescriptor.getScopeChain() - const configOptions = {scope: scopeDescriptor} - const params = {} - for (const [settingKey, paramName] of EDITOR_PARAMS_BY_SETTING_KEY) { - params[paramName] = this.config.get(settingKey, configOptions) - } - - editor.update(params) + editor.update(this.textEditorParamsForScope(scopeDescriptor)) if (!this.scopesWithConfigSubscriptions.has(scopeChain)) { this.scopesWithConfigSubscriptions.add(scopeChain) + const configOptions = {scope: scopeDescriptor} for (const [settingKey, paramName] of EDITOR_PARAMS_BY_SETTING_KEY) { this.subscriptions.add( @@ -325,6 +350,15 @@ export default class TextEditorRegistry { ) } } + + textEditorParamsForScope (scopeDescriptor) { + const result = {} + const configOptions = {scope: scopeDescriptor} + for (const [settingKey, paramName] of EDITOR_PARAMS_BY_SETTING_KEY) { + result[paramName] = this.config.get(settingKey, configOptions) + } + return result + } } function shouldEditorUseSoftTabs (editor, tabType, softTabs) { diff --git a/src/workspace.coffee b/src/workspace.coffee index 63631be73..d49fe7d69 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -561,10 +561,7 @@ class Workspace extends Model throw error @project.bufferForPath(filePath, options).then (buffer) => - new TextEditor(Object.assign( - {@clipboard, @assert, buffer, largeFileMode}, - options - )) + @textEditorRegistry.build(Object.assign({buffer, largeFileMode}, options)) handleGrammarUsed: (grammar) -> return unless grammar? @@ -581,7 +578,7 @@ class Workspace extends Model # # Returns a {TextEditor}. buildTextEditor: (params) -> - editor = new TextEditor(Object.assign({@clipboard, @assert}, params)) + editor = @textEditorRegistry.build(params) subscriptions = new CompositeDisposable( @textEditorRegistry.maintainGrammar(editor) @textEditorRegistry.maintainConfig(editor),