From 64b4954492bbd33eababf0ea0b575947ccba21f0 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Tue, 21 Nov 2017 23:35:26 +0100 Subject: [PATCH 01/16] Improve spec stack traces --- spec/atom-reporter.coffee | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/spec/atom-reporter.coffee b/spec/atom-reporter.coffee index 455afcb27..1df74f64d 100644 --- a/spec/atom-reporter.coffee +++ b/spec/atom-reporter.coffee @@ -9,34 +9,40 @@ ipcHelpers = require '../src/ipc-helpers' formatStackTrace = (spec, message='', stackTrace) -> return stackTrace unless stackTrace + # at ... (.../jasmine.js:1:2) jasminePattern = /^\s*at\s+.*\(?.*[/\\]jasmine(-[^/\\]*)?\.js:\d+:\d+\)?\s*$/ - firstJasmineLinePattern = /^\s*at [/\\].*[/\\]jasmine(-[^/\\]*)?\.js:\d+:\d+\)?\s*$/ + # at jasmine.Something... (.../jasmine.js:1:2) + firstJasmineLinePattern = /^\s*at\s+jasmine\.[A-Z][^\s]*\s+\(?.*[/\\]jasmine(-[^/\\]*)?\.js:\d+:\d+\)?\s*$/ lines = [] for line in stackTrace.split('\n') - lines.push(line) unless jasminePattern.test(line) break if firstJasmineLinePattern.test(line) + lines.push(line) unless jasminePattern.test(line) # Remove first line of stack when it is the same as the error message errorMatch = lines[0]?.match(/^Error: (.*)/) lines.shift() if message.trim() is errorMatch?[1]?.trim() - for line, index in lines - # Remove prefix of lines matching: at jasmine.Spec. (path:1:2) - prefixMatch = line.match(/at jasmine\.Spec\. \(([^)]+)\)/) - line = "at #{prefixMatch[1]}" if prefixMatch + lines = lines.map (line) -> + line = line + # at jasmine.Spec. (path:1:2) -> at path:1:2 + .replace(/at jasmine\.Spec\. \(([^)]+)\)/, 'at $1') + # at it (path:1:2) -> at path:1:2 + .replace(/at f*it \(([^)]+)\)/, 'at $1') + # at spec/file-test.js -> at file-test.js + .replace("at #{spec.specDirectory}#{path.sep}", 'at ') + # (spec/file-test.js:1:2) -> (file-test.js:1:2) + .replace("(#{spec.specDirectory}#{path.sep}", '(') - # Relativize locations to spec directory - if process.platform is 'win32' + if process.platform is 'win32' and /file:\/\/\//.test(line) + # file:///C:/some/file -> C:\some\file line = line.replace('file:///', '').replace(///#{path.posix.sep}///g, path.win32.sep) - line = line.replace("at #{spec.specDirectory}#{path.sep}", 'at ') - lines[index] = line.replace("(#{spec.specDirectory}#{path.sep}", '(') # at step (path:1:2) - lines = lines.map (line) -> line.trim() + return line.trim() + lines.join('\n').trim() module.exports = class AtomReporter - constructor: -> @element = document.createElement('div') @element.classList.add('spec-reporter-container') From 34df49b491f6d98d4eaacadb6956a30d9305a573 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 22 Nov 2017 00:02:42 +0100 Subject: [PATCH 02/16] More cleanup --- spec/atom-reporter.coffee | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/spec/atom-reporter.coffee b/spec/atom-reporter.coffee index 1df74f64d..ba06cd31d 100644 --- a/spec/atom-reporter.coffee +++ b/spec/atom-reporter.coffee @@ -23,21 +23,21 @@ formatStackTrace = (spec, message='', stackTrace) -> lines.shift() if message.trim() is errorMatch?[1]?.trim() lines = lines.map (line) -> - line = line - # at jasmine.Spec. (path:1:2) -> at path:1:2 - .replace(/at jasmine\.Spec\. \(([^)]+)\)/, 'at $1') - # at it (path:1:2) -> at path:1:2 - .replace(/at f*it \(([^)]+)\)/, 'at $1') - # at spec/file-test.js -> at file-test.js - .replace("at #{spec.specDirectory}#{path.sep}", 'at ') - # (spec/file-test.js:1:2) -> (file-test.js:1:2) - .replace("(#{spec.specDirectory}#{path.sep}", '(') + line = line.trim() + if line.startsWith('at ') + line = line + # at jasmine.Spec. (path:1:2) -> at path:1:2 + .replace(/^at jasmine\.Spec\. \(([^)]+)\)/, 'at $1') + # at it (path:1:2) -> at path:1:2 + .replace(/^at f*it \(([^)]+)\)/, 'at $1') + # at spec/file-test.js -> at file-test.js + .replace(spec.specDirectory + path.sep, '') - if process.platform is 'win32' and /file:\/\/\//.test(line) - # file:///C:/some/file -> C:\some\file - line = line.replace('file:///', '').replace(///#{path.posix.sep}///g, path.win32.sep) + if process.platform is 'win32' and /file:\/\/\//.test(line) + # file:///C:/some/file -> C:\some\file + line = line.replace('file:///', '').replace(///#{path.posix.sep}///g, path.win32.sep) - return line.trim() + return line lines.join('\n').trim() From 6633714e110a7d5170971e08717d5c99fb57689d Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 22 Nov 2017 00:31:06 +0100 Subject: [PATCH 03/16] Fix regression and minimize chance for incorrect replacements --- spec/atom-reporter.coffee | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/spec/atom-reporter.coffee b/spec/atom-reporter.coffee index ba06cd31d..a522d9298 100644 --- a/spec/atom-reporter.coffee +++ b/spec/atom-reporter.coffee @@ -23,9 +23,14 @@ formatStackTrace = (spec, message='', stackTrace) -> lines.shift() if message.trim() is errorMatch?[1]?.trim() lines = lines.map (line) -> - line = line.trim() - if line.startsWith('at ') - line = line + # Only format actual stacktrace lines + if /^\s*at\s/.test(line) + # Needs to occur before path relativization + if process.platform is 'win32' and /file:\/\/\//.test(line) + # file:///C:/some/file -> C:\some\file + line = line.replace('file:///', '').replace(///#{path.posix.sep}///g, path.win32.sep) + + line = line.trim() # at jasmine.Spec. (path:1:2) -> at path:1:2 .replace(/^at jasmine\.Spec\. \(([^)]+)\)/, 'at $1') # at it (path:1:2) -> at path:1:2 @@ -33,10 +38,6 @@ formatStackTrace = (spec, message='', stackTrace) -> # at spec/file-test.js -> at file-test.js .replace(spec.specDirectory + path.sep, '') - if process.platform is 'win32' and /file:\/\/\//.test(line) - # file:///C:/some/file -> C:\some\file - line = line.replace('file:///', '').replace(///#{path.posix.sep}///g, path.win32.sep) - return line lines.join('\n').trim() From 909caa2a59d96059180ba1c78dd08ae87b2e67d3 Mon Sep 17 00:00:00 2001 From: Katrina Uychaco Date: Tue, 28 Nov 2017 20:01:31 -0800 Subject: [PATCH 04/16] Add 'readonly' attribute to element --- spec/text-editor-element-spec.js | 14 ++++++++++++++ src/text-editor-component.js | 14 ++++++++++---- src/text-editor-element.js | 6 +++++- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/spec/text-editor-element-spec.js b/spec/text-editor-element-spec.js index 7cdd374a1..02c3c0ba0 100644 --- a/spec/text-editor-element-spec.js +++ b/spec/text-editor-element-spec.js @@ -70,6 +70,20 @@ describe('TextEditorElement', () => { expect(element.getModel().isLineNumberGutterVisible()).toBe(false) }) + it("honors the 'readonly' attribute", async function() { + console.log('set attribute'); + jasmineContent.innerHTML = "" + const element = jasmineContent.firstChild + + expect(element.getComponent().isInputEnabled()).toBe(false) + + element.removeAttribute('readonly') + expect(element.getComponent().isInputEnabled()).toBe(true) + + element.setAttribute('readonly', true) + expect(element.getComponent().isInputEnabled()).toBe(false) + }) + it('honors the text content', () => { jasmineContent.innerHTML = 'testing' const element = jasmineContent.firstChild diff --git a/src/text-editor-component.js b/src/text-editor-component.js index da6ec452d..c6135087c 100644 --- a/src/text-editor-component.js +++ b/src/text-editor-component.js @@ -55,6 +55,8 @@ class TextEditorComponent { constructor (props) { this.props = props + this.setInputEnabled(!this.props.readonly) + if (!props.model) { props.model = new TextEditor({mini: props.mini}) } @@ -460,9 +462,13 @@ class TextEditorComponent { } } - let attributes = null + let attributes = {} if (model.isMini()) { - attributes = {mini: ''} + attributes.mini = '' + } + + if (!this.isInputEnabled()) { + attributes.readonly = '' } const dataset = {encoding: model.getEncoding()} @@ -819,7 +825,7 @@ class TextEditorComponent { const oldClassList = this.classList const newClassList = ['editor'] - if (this.focused) newClassList.push('is-focused') + if (this.focused && this.isInputEnabled()) newClassList.push('is-focused') if (model.isMini()) newClassList.push('mini') for (var i = 0; i < model.selections.length; i++) { if (!model.selections[i].isEmpty()) { @@ -2966,7 +2972,7 @@ class TextEditorComponent { } isInputEnabled (inputEnabled) { - return this.props.inputEnabled != null ? this.props.inputEnabled : true + return this.props.inputEnabled; } getHiddenInput () { diff --git a/src/text-editor-element.js b/src/text-editor-element.js index d56c5596b..83ef5da36 100644 --- a/src/text-editor-element.js +++ b/src/text-editor-element.js @@ -59,6 +59,9 @@ class TextEditorElement extends HTMLElement { case 'gutter-hidden': this.getModel().update({lineNumberGutterVisible: newValue == null}) break + case 'readonly': + this.getComponent().setInputEnabled(newValue == null) + break } } } @@ -275,7 +278,8 @@ class TextEditorElement extends HTMLElement { this.component = new TextEditorComponent({ element: this, mini: this.hasAttribute('mini'), - updatedSynchronously: this.updatedSynchronously + updatedSynchronously: this.updatedSynchronously, + readonly: this.hasAttribute('readonly') }) this.updateModelFromAttributes() } From aeb9af63dfba1c475b0e6b7f74d8ed4c04355fa2 Mon Sep 17 00:00:00 2001 From: Katrina Uychaco Date: Tue, 28 Nov 2017 21:14:40 -0800 Subject: [PATCH 05/16] Store readOnly state on the TextEditor model --- src/text-editor-component.js | 8 +++----- src/text-editor-element.js | 4 ++-- src/text-editor.js | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/text-editor-component.js b/src/text-editor-component.js index c6135087c..4557469dc 100644 --- a/src/text-editor-component.js +++ b/src/text-editor-component.js @@ -55,10 +55,8 @@ class TextEditorComponent { constructor (props) { this.props = props - this.setInputEnabled(!this.props.readonly) - if (!props.model) { - props.model = new TextEditor({mini: props.mini}) + props.model = new TextEditor({mini: props.mini, readOnly: props.readOnly}) } this.props.model.component = this @@ -2968,11 +2966,11 @@ class TextEditorComponent { } setInputEnabled (inputEnabled) { - this.props.inputEnabled = inputEnabled + this.props.model.update({readOnly: !inputEnabled}) } isInputEnabled (inputEnabled) { - return this.props.inputEnabled; + return !this.props.model.isReadOnly(); } getHiddenInput () { diff --git a/src/text-editor-element.js b/src/text-editor-element.js index 83ef5da36..7218b7f05 100644 --- a/src/text-editor-element.js +++ b/src/text-editor-element.js @@ -60,7 +60,7 @@ class TextEditorElement extends HTMLElement { this.getModel().update({lineNumberGutterVisible: newValue == null}) break case 'readonly': - this.getComponent().setInputEnabled(newValue == null) + this.getModel().update({readOnly: newValue != null}) break } } @@ -279,7 +279,7 @@ class TextEditorElement extends HTMLElement { element: this, mini: this.hasAttribute('mini'), updatedSynchronously: this.updatedSynchronously, - readonly: this.hasAttribute('readonly') + readOnly: this.hasAttribute('readonly') }) this.updateModelFromAttributes() } diff --git a/src/text-editor.js b/src/text-editor.js index a0b9d19a0..aef6ffc1a 100644 --- a/src/text-editor.js +++ b/src/text-editor.js @@ -121,6 +121,7 @@ class TextEditor { this.decorationManager = params.decorationManager this.selectionsMarkerLayer = params.selectionsMarkerLayer this.mini = (params.mini != null) ? params.mini : false + this.readOnly = (params.readOnly != null) ? params.readOnly : false this.placeholderText = params.placeholderText this.showLineNumbers = params.showLineNumbers this.largeFileMode = params.largeFileMode @@ -404,6 +405,15 @@ class TextEditor { } break + case 'readOnly': + if (value !== this.readOnly) { + this.readOnly = value + if (this.component != null) { + this.component.scheduleUpdate() + } + } + break + case 'placeholderText': if (value !== this.placeholderText) { this.placeholderText = value @@ -538,6 +548,7 @@ class TextEditor { softWrapAtPreferredLineLength: this.softWrapAtPreferredLineLength, preferredLineLength: this.preferredLineLength, mini: this.mini, + readOnly: this.readOnly, editorWidthInChars: this.editorWidthInChars, width: this.width, largeFileMode: this.largeFileMode, @@ -968,6 +979,12 @@ class TextEditor { isMini () { return this.mini } + setReadOnly (readOnly) { + this.update({readOnly}) + } + + isReadOnly () { return this.readOnly } + onDidChangeMini (callback) { return this.emitter.on('did-change-mini', callback) } From a993742f7fbe8028b4ee154465db35e810549538 Mon Sep 17 00:00:00 2001 From: Katrina Uychaco Date: Tue, 28 Nov 2017 22:06:33 -0800 Subject: [PATCH 06/16] :shirt: :fire: semicolon --- src/text-editor-component.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/text-editor-component.js b/src/text-editor-component.js index 4557469dc..08af5ada1 100644 --- a/src/text-editor-component.js +++ b/src/text-editor-component.js @@ -2970,7 +2970,7 @@ class TextEditorComponent { } isInputEnabled (inputEnabled) { - return !this.props.model.isReadOnly(); + return !this.props.model.isReadOnly() } getHiddenInput () { From aaed3c744a491fd59501f41dded19516075ddde8 Mon Sep 17 00:00:00 2001 From: Justin Ratner Date: Thu, 30 Nov 2017 15:03:19 -0700 Subject: [PATCH 07/16] :arrow_up: atom-package-manager@1.18.11 --- apm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm/package.json b/apm/package.json index 336544d3e..b15e4a30f 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "1.18.10" + "atom-package-manager": "1.18.11" } } From 49d8d9421857abbdebd6620fff70b3f23b5e61a3 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 1 Dec 2017 09:46:46 -0800 Subject: [PATCH 08/16] :art: workspace-spec.js --- spec/workspace-spec.js | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/spec/workspace-spec.js b/spec/workspace-spec.js index 83a4429b6..43f9e250d 100644 --- a/spec/workspace-spec.js +++ b/spec/workspace-spec.js @@ -1,5 +1,6 @@ const path = require('path') const temp = require('temp').track() +const dedent = require('dedent') const TextEditor = require('../src/text-editor') const Workspace = require('../src/workspace') const Project = require('../src/project') @@ -1206,8 +1207,8 @@ describe('Workspace', () => { }) }) - describe('::onDidStopChangingActivePaneItem()', function () { - it('invokes observers when the active item of the active pane stops changing', function () { + describe('::onDidStopChangingActivePaneItem()', () => { + it('invokes observers when the active item of the active pane stops changing', () => { const pane1 = atom.workspace.getCenter().getActivePane() const pane2 = pane1.splitRight({items: [document.createElement('div'), document.createElement('div')]}); atom.workspace.getLeftDock().getActivePane().addItem(document.createElement('div')) @@ -1364,7 +1365,7 @@ describe('Workspace', () => { describe('::getActiveTextEditor()', () => { describe("when the workspace center's active pane item is a text editor", () => { - describe('when the workspace center has focus', function () { + describe('when the workspace center has focus', () => { it('returns the text editor', () => { const workspaceCenter = workspace.getCenter() const editor = new TextEditor() @@ -1375,7 +1376,7 @@ describe('Workspace', () => { }) }) - describe('when a dock has focus', function () { + describe('when a dock has focus', () => { it('returns the text editor', () => { const workspaceCenter = workspace.getCenter() const editor = new TextEditor() @@ -1536,11 +1537,10 @@ describe('Workspace', () => { waitsForPromise(() => atom.workspace.open('sample.coffee')) - runs(function () { - atom.workspace.getActiveTextEditor().setText(`\ -i = /test/; #FIXME\ -` - ) + runs(() => { + atom.workspace.getActiveTextEditor().setText(dedent ` + i = /test/; #FIXME\ + `) const atom2 = new AtomEnvironment({applicationDelegate: atom.applicationDelegate}) atom2.initialize({ @@ -2867,4 +2867,6 @@ i = /test/; #FIXME\ }) }) -const escapeStringRegex = str => str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&') +function escapeStringRegex (string) { + return string.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&') +} From 6e2ac3548f0ddc474fd29248227e59edeefe35e6 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 1 Dec 2017 09:58:19 -0800 Subject: [PATCH 09/16] Ensure that all opened editors' buffers are added to the project Assigning a language mode happens when adding a buffer to the project, so we need to guarantee this happens to all buffers used by visible editors. --- spec/workspace-spec.js | 13 +++++++++++++ src/workspace.js | 3 +++ 2 files changed, 16 insertions(+) diff --git a/spec/workspace-spec.js b/spec/workspace-spec.js index 43f9e250d..6bc3199ba 100644 --- a/spec/workspace-spec.js +++ b/spec/workspace-spec.js @@ -1,6 +1,7 @@ const path = require('path') const temp = require('temp').track() const dedent = require('dedent') +const TextBuffer = require('text-buffer') const TextEditor = require('../src/text-editor') const Workspace = require('../src/workspace') const Project = require('../src/project') @@ -933,6 +934,18 @@ describe('Workspace', () => { }) }) }) + + describe('when opening an editor with a buffer that isn\'t part of the project', () => { + it('adds the buffer to the project', async () => { + const buffer = new TextBuffer() + const editor = new TextEditor({buffer}) + + await atom.workspace.open(editor) + + expect(atom.project.getBuffers().map(buffer => buffer.id)).toContain(buffer.id) + expect(buffer.getLanguageMode().getLanguageId()).toBe('text.plain.null-grammar') + }) + }) }) describe('finding items in the workspace', () => { diff --git a/src/workspace.js b/src/workspace.js index 9f2ad397b..5e85401ef 100644 --- a/src/workspace.js +++ b/src/workspace.js @@ -497,6 +497,9 @@ module.exports = class Workspace extends Model { this.textEditorRegistry.maintainConfig(item), item.observeGrammar(this.handleGrammarUsed.bind(this)) ) + if (!this.project.findBufferForId(item.buffer.id)) { + this.project.addBuffer(item.buffer) + } item.onDidDestroy(() => { subscriptions.dispose() }) this.emitter.emit('did-add-text-editor', {textEditor: item, pane, index}) } From 733770246c822a2c710ea0517057d7c4be826e4a Mon Sep 17 00:00:00 2001 From: Justin Ratner Date: Sun, 3 Dec 2017 21:03:11 -0700 Subject: [PATCH 10/16] :arrow_up: notifications@0.70.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dc3313577..922fbba8d 100644 --- a/package.json +++ b/package.json @@ -120,7 +120,7 @@ "link": "0.31.4", "markdown-preview": "0.159.18", "metrics": "1.2.6", - "notifications": "0.69.2", + "notifications": "0.70.0", "open-on-github": "1.3.1", "package-generator": "1.3.0", "settings-view": "0.253.0", From f24e74193e09ce17306f040da95e5573c83f507c Mon Sep 17 00:00:00 2001 From: Justin Ratner Date: Sun, 3 Dec 2017 21:05:26 -0700 Subject: [PATCH 11/16] :arrow_up: command-palette@0.43.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 922fbba8d..d7e86b32f 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "background-tips": "0.27.1", "bookmarks": "0.45.0", "bracket-matcher": "0.88.0", - "command-palette": "0.42.1", + "command-palette": "0.43.0", "dalek": "0.2.1", "deprecation-cop": "0.56.9", "dev-live-reload": "0.48.1", From ea183232836ebdf334c8c52cc8e89e721e8bfcb5 Mon Sep 17 00:00:00 2001 From: Justin Ratner Date: Sun, 3 Dec 2017 23:19:40 -0700 Subject: [PATCH 12/16] :arrow_up: notifications@0.70.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d7e86b32f..7a526e3de 100644 --- a/package.json +++ b/package.json @@ -120,7 +120,7 @@ "link": "0.31.4", "markdown-preview": "0.159.18", "metrics": "1.2.6", - "notifications": "0.70.0", + "notifications": "0.70.1", "open-on-github": "1.3.1", "package-generator": "1.3.0", "settings-view": "0.253.0", From 129f5a34cbb608f29d8a824f7db924831acb45d1 Mon Sep 17 00:00:00 2001 From: Justin Ratner Date: Mon, 4 Dec 2017 01:20:18 -0700 Subject: [PATCH 13/16] :arrow_up: notifications@0.70.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7a526e3de..2af021a4f 100644 --- a/package.json +++ b/package.json @@ -120,7 +120,7 @@ "link": "0.31.4", "markdown-preview": "0.159.18", "metrics": "1.2.6", - "notifications": "0.70.1", + "notifications": "0.70.2", "open-on-github": "1.3.1", "package-generator": "1.3.0", "settings-view": "0.253.0", From d4dd08da2244102121a275d97df556ff9cba85ed Mon Sep 17 00:00:00 2001 From: Justin Ratner Date: Mon, 4 Dec 2017 10:28:22 -0700 Subject: [PATCH 14/16] Use buildIndentString method instead of hard-coding spaces --- src/text-editor.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/text-editor.js b/src/text-editor.js index bcd9c19d3..851718946 100644 --- a/src/text-editor.js +++ b/src/text-editor.js @@ -4522,8 +4522,7 @@ class TextEditor { ? minBlankIndentLevel : 0 - const tabLength = this.getTabLength() - const indentString = ' '.repeat(tabLength * minIndentLevel) + const indentString = this.buildIndentString(minIndentLevel) for (let row = start; row <= end; row++) { const line = this.buffer.lineForRow(row) if (NON_WHITESPACE_REGEXP.test(line)) { From 70e773fa7b2e5b9944088722326a8a0ea7dae0fd Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Mon, 4 Dec 2017 13:12:08 -0800 Subject: [PATCH 15/16] Ensure read-only text editors are not considered 'modified'. Also clear read-only flag on successful save. --- spec/text-editor-spec.js | 17 +++++++++++++++++ src/text-editor.js | 8 +++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/spec/text-editor-spec.js b/spec/text-editor-spec.js index 198cf1c43..f15a66e30 100644 --- a/spec/text-editor-spec.js +++ b/spec/text-editor-spec.js @@ -85,6 +85,23 @@ describe('TextEditor', () => { }) }) + describe('when the editor is readonly', () => { + it('overrides TextBuffer.isModified to return false', async () => { + const editor = await atom.workspace.open(null, {readOnly: true}) + editor.setText('I am altering the buffer, pray I do not alter it any further') + expect(editor.isModified()).toBe(false) + editor.setReadOnly(false) + expect(editor.isModified()).toBe(true) + }) + it('clears the readonly status when saved', async () => { + const editor = await atom.workspace.open(null, {readOnly: true}) + editor.setText('I am altering the buffer, pray I do not alter it any further') + expect(editor.isReadOnly()).toBe(true) + await editor.saveAs(temp.openSync('was-readonly').path) + expect(editor.isReadOnly()).toBe(false) + }) + }) + describe('when the editor is constructed with the largeFileMode option set to true', () => { it("loads the editor but doesn't tokenize", async () => { editor = await atom.workspace.openTextFile('sample.js', {largeFileMode: true}) diff --git a/src/text-editor.js b/src/text-editor.js index aef6ffc1a..0b14e45b6 100644 --- a/src/text-editor.js +++ b/src/text-editor.js @@ -411,6 +411,7 @@ class TextEditor { if (this.component != null) { this.component.scheduleUpdate() } + this.buffer.emitModifiedStatusChanged(this.isModified()) } break @@ -575,6 +576,11 @@ class TextEditor { this.disposables.add(this.buffer.onDidChangeModified(() => { if (!this.hasTerminatedPendingState && this.buffer.isModified()) this.terminatePendingState() })) + this.disposables.add(this.buffer.onDidSave(() => { + if (this.isReadOnly()) { + this.setReadOnly(false) + } + })) } terminatePendingState () { @@ -1126,7 +1132,7 @@ class TextEditor { setEncoding (encoding) { this.buffer.setEncoding(encoding) } // Essential: Returns {Boolean} `true` if this editor has been modified. - isModified () { return this.buffer.isModified() } + isModified () { return this.isReadOnly() ? false : this.buffer.isModified() } // Essential: Returns {Boolean} `true` if this editor has no content. isEmpty () { return this.buffer.isEmpty() } From abc0d3c534743897c02a8e434e2ccabde9026c07 Mon Sep 17 00:00:00 2001 From: Damien Guard Date: Mon, 4 Dec 2017 13:13:03 -0800 Subject: [PATCH 16/16] Remove stray console log --- spec/text-editor-element-spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/text-editor-element-spec.js b/spec/text-editor-element-spec.js index 02c3c0ba0..f298ee3a4 100644 --- a/spec/text-editor-element-spec.js +++ b/spec/text-editor-element-spec.js @@ -71,7 +71,6 @@ describe('TextEditorElement', () => { }) it("honors the 'readonly' attribute", async function() { - console.log('set attribute'); jasmineContent.innerHTML = "" const element = jasmineContent.firstChild