From d65a0971f95b39bac326e195c903c34e438b0328 Mon Sep 17 00:00:00 2001 From: Jason Rudolph Date: Fri, 18 May 2018 17:29:49 -0400 Subject: [PATCH 1/8] Fix #17356 Refs: https://github.com/electron/electron/issues/10732#issuecomment-390321086 --- src/main-process/start.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main-process/start.js b/src/main-process/start.js index 23b4df594..bd4a78270 100644 --- a/src/main-process/start.js +++ b/src/main-process/start.js @@ -33,6 +33,7 @@ module.exports = function start (resourcePath, startTime) { console.log = nslog app.commandLine.appendSwitch('enable-experimental-web-platform-features') + app.commandLine.appendSwitch('force-color-profile', 'srgb') const args = parseCommandLine(process.argv.slice(1)) atomPaths.setAtomHome(app.getPath('home')) From 82ba358aa93e784e6a1079514861d0e124565b43 Mon Sep 17 00:00:00 2001 From: Jason Rudolph Date: Thu, 31 May 2018 17:44:26 -0400 Subject: [PATCH 2/8] Read user's custom Electron switches from config file --- .../electron-switch-store.test.js | 47 +++++++++++++++++++ src/main-process/electron-switch-store.js | 31 ++++++++++++ src/main-process/start.js | 9 +++- 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 spec/main-process/electron-switch-store.test.js create mode 100644 src/main-process/electron-switch-store.js diff --git a/spec/main-process/electron-switch-store.test.js b/spec/main-process/electron-switch-store.test.js new file mode 100644 index 000000000..578f6b6ec --- /dev/null +++ b/spec/main-process/electron-switch-store.test.js @@ -0,0 +1,47 @@ +const temp = require('temp').track() +const fs = require('fs-plus') +const path = require('path') +const ElectronSwitchStore = require('../../src/main-process/electron-switch-store') + +describe.only('entries()', function () { + let userDataDir, electronSwitchesFilePath + + beforeEach(() => { + userDataDir = fs.realpathSync(temp.mkdirSync('atom-home')) + electronSwitchesFilePath = path.join(userDataDir, '.electron-switches') + }) + + afterEach(async () => { + if (fs.existsSync(electronSwitchesFilePath)) { + fs.unlinkSync(electronSwitchesFilePath) + } + }) + + it('returns an iterator over each switch specified in the config file', () => { + const fileContents = '\n' + + 'force-color-profile srgb\n' + + 'foo bar' + + fs.writeFileSync(electronSwitchesFilePath, fileContents) + + const store = new ElectronSwitchStore({filePath: electronSwitchesFilePath}) + const entries = new Map(store.entries()) + assert.equal(entries.size, 2) + assert.equal(entries.get('force-color-profile'), 'srgb') + assert.equal(entries.get('foo'), 'bar') + }) + + it('returns an empty iterator when the config file does not exist', () => { + assert(!fs.existsSync(electronSwitchesFilePath)) + const store = new ElectronSwitchStore({filePath: electronSwitchesFilePath}) + const entries = new Map(store.entries()) + assert.equal(entries.size, 0) + }) + + it('returns an empty iterator when the config file is empty', () => { + fs.writeFileSync(electronSwitchesFilePath, '') + const store = new ElectronSwitchStore({filePath: electronSwitchesFilePath}) + const entries = new Map(store.entries()) + assert.equal(entries.size, 0) + }) +}) diff --git a/src/main-process/electron-switch-store.js b/src/main-process/electron-switch-store.js new file mode 100644 index 000000000..2e3bf3077 --- /dev/null +++ b/src/main-process/electron-switch-store.js @@ -0,0 +1,31 @@ +const fs = require('fs') + +module.exports = +class ElectronSwitchStore { + constructor ({filePath}) { + this.store = this.load(filePath) + } + + entries () { + return this.store.entries() + } + + // Private + load (filePath) { + const map = new Map() + + if (fs.existsSync(filePath)) { + const lines = fs.readFileSync(filePath, 'utf8').split(/\r?\n/g) + for (const line of lines) { + const indexOfNameValueSeparator = line.indexOf(' ') + const name = line.slice(0, indexOfNameValueSeparator) + const value = line.slice(indexOfNameValueSeparator + 1) + if (name.length > 0) { + map.set(name, value) + } + } + } + + return map + } +} diff --git a/src/main-process/start.js b/src/main-process/start.js index bd4a78270..311451fbc 100644 --- a/src/main-process/start.js +++ b/src/main-process/start.js @@ -5,6 +5,7 @@ const temp = require('temp').track() const parseCommandLine = require('./parse-command-line') const startCrashReporter = require('../crash-reporter-start') const atomPaths = require('../atom-paths') +const ElectronSwitchStore = require('./electron-switch-store') module.exports = function start (resourcePath, startTime) { global.shellStartTime = startTime @@ -33,13 +34,19 @@ module.exports = function start (resourcePath, startTime) { console.log = nslog app.commandLine.appendSwitch('enable-experimental-web-platform-features') - app.commandLine.appendSwitch('force-color-profile', 'srgb') const args = parseCommandLine(process.argv.slice(1)) atomPaths.setAtomHome(app.getPath('home')) atomPaths.setUserData(app) setupCompileCache() + const electronSwitchStore = new ElectronSwitchStore({ + filePath: path.join(app.getPath('userData'), '.electron-switches') + }) + for (const [name, value] of electronSwitchStore.entries()) { + app.commandLine.appendSwitch(name, value) + } + if (handleStartupEventWithSquirrel()) { return } else if (args.test && args.mainProcess) { From c71de84962b56d948309345a2b07b3edc6502794 Mon Sep 17 00:00:00 2001 From: Jason Rudolph Date: Fri, 1 Jun 2018 11:02:00 -0400 Subject: [PATCH 3/8] Look for .electron-switches in ATOM_HOME --- src/main-process/start.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main-process/start.js b/src/main-process/start.js index 311451fbc..5ecc1c677 100644 --- a/src/main-process/start.js +++ b/src/main-process/start.js @@ -41,7 +41,7 @@ module.exports = function start (resourcePath, startTime) { setupCompileCache() const electronSwitchStore = new ElectronSwitchStore({ - filePath: path.join(app.getPath('userData'), '.electron-switches') + filePath: path.join(process.env.ATOM_HOME, '.electron-switches') }) for (const [name, value] of electronSwitchStore.entries()) { app.commandLine.appendSwitch(name, value) From 6985fb0ff39956dd341afe27ac1b9c2292f8b918 Mon Sep 17 00:00:00 2001 From: Jason Rudolph Date: Fri, 1 Jun 2018 13:58:21 -0400 Subject: [PATCH 4/8] Use Atom's standard config file to set custom color profile --- .../electron-switch-store.test.js | 47 ------------------- src/main-process/electron-switch-store.js | 31 ------------ src/main-process/start.js | 24 +++++++--- 3 files changed, 18 insertions(+), 84 deletions(-) delete mode 100644 spec/main-process/electron-switch-store.test.js delete mode 100644 src/main-process/electron-switch-store.js diff --git a/spec/main-process/electron-switch-store.test.js b/spec/main-process/electron-switch-store.test.js deleted file mode 100644 index 578f6b6ec..000000000 --- a/spec/main-process/electron-switch-store.test.js +++ /dev/null @@ -1,47 +0,0 @@ -const temp = require('temp').track() -const fs = require('fs-plus') -const path = require('path') -const ElectronSwitchStore = require('../../src/main-process/electron-switch-store') - -describe.only('entries()', function () { - let userDataDir, electronSwitchesFilePath - - beforeEach(() => { - userDataDir = fs.realpathSync(temp.mkdirSync('atom-home')) - electronSwitchesFilePath = path.join(userDataDir, '.electron-switches') - }) - - afterEach(async () => { - if (fs.existsSync(electronSwitchesFilePath)) { - fs.unlinkSync(electronSwitchesFilePath) - } - }) - - it('returns an iterator over each switch specified in the config file', () => { - const fileContents = '\n' + - 'force-color-profile srgb\n' + - 'foo bar' - - fs.writeFileSync(electronSwitchesFilePath, fileContents) - - const store = new ElectronSwitchStore({filePath: electronSwitchesFilePath}) - const entries = new Map(store.entries()) - assert.equal(entries.size, 2) - assert.equal(entries.get('force-color-profile'), 'srgb') - assert.equal(entries.get('foo'), 'bar') - }) - - it('returns an empty iterator when the config file does not exist', () => { - assert(!fs.existsSync(electronSwitchesFilePath)) - const store = new ElectronSwitchStore({filePath: electronSwitchesFilePath}) - const entries = new Map(store.entries()) - assert.equal(entries.size, 0) - }) - - it('returns an empty iterator when the config file is empty', () => { - fs.writeFileSync(electronSwitchesFilePath, '') - const store = new ElectronSwitchStore({filePath: electronSwitchesFilePath}) - const entries = new Map(store.entries()) - assert.equal(entries.size, 0) - }) -}) diff --git a/src/main-process/electron-switch-store.js b/src/main-process/electron-switch-store.js deleted file mode 100644 index 2e3bf3077..000000000 --- a/src/main-process/electron-switch-store.js +++ /dev/null @@ -1,31 +0,0 @@ -const fs = require('fs') - -module.exports = -class ElectronSwitchStore { - constructor ({filePath}) { - this.store = this.load(filePath) - } - - entries () { - return this.store.entries() - } - - // Private - load (filePath) { - const map = new Map() - - if (fs.existsSync(filePath)) { - const lines = fs.readFileSync(filePath, 'utf8').split(/\r?\n/g) - for (const line of lines) { - const indexOfNameValueSeparator = line.indexOf(' ') - const name = line.slice(0, indexOfNameValueSeparator) - const value = line.slice(indexOfNameValueSeparator + 1) - if (name.length > 0) { - map.set(name, value) - } - } - } - - return map - } -} diff --git a/src/main-process/start.js b/src/main-process/start.js index 5ecc1c677..8babb65ed 100644 --- a/src/main-process/start.js +++ b/src/main-process/start.js @@ -5,7 +5,9 @@ const temp = require('temp').track() const parseCommandLine = require('./parse-command-line') const startCrashReporter = require('../crash-reporter-start') const atomPaths = require('../atom-paths') -const ElectronSwitchStore = require('./electron-switch-store') +const fs = require('fs') +const CSON = require('season') +const Config = require('../config') module.exports = function start (resourcePath, startTime) { global.shellStartTime = startTime @@ -40,11 +42,10 @@ module.exports = function start (resourcePath, startTime) { atomPaths.setUserData(app) setupCompileCache() - const electronSwitchStore = new ElectronSwitchStore({ - filePath: path.join(process.env.ATOM_HOME, '.electron-switches') - }) - for (const [name, value] of electronSwitchStore.entries()) { - app.commandLine.appendSwitch(name, value) + const config = getConfig() + const colorProfile = config.get('core.forceColorProfile') + if (colorProfile) { + app.commandLine.appendSwitch('force-color-profile', colorProfile) } if (handleStartupEventWithSquirrel()) { @@ -105,3 +106,14 @@ function setupCompileCache () { CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME) CompileCache.install(process.resourcesPath, require) } + +function getConfig () { + const configFilePath = fs.existsSync(path.join(process.env.ATOM_HOME, 'config.json')) + ? path.join(process.env.ATOM_HOME, 'config.json') + : path.join(process.env.ATOM_HOME, 'config.cson') + + const configFileData = CSON.readFileSync(configFilePath) + const config = new Config() + config.resetUserSettings(configFileData) + return config +} From b67f8ac2ce48ed8b6f96c6d05aac9ccab7db661f Mon Sep 17 00:00:00 2001 From: Jason Rudolph Date: Fri, 1 Jun 2018 15:04:46 -0400 Subject: [PATCH 5/8] :shirt: --- src/main-process/start.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main-process/start.js b/src/main-process/start.js index 8babb65ed..682532998 100644 --- a/src/main-process/start.js +++ b/src/main-process/start.js @@ -45,7 +45,7 @@ module.exports = function start (resourcePath, startTime) { const config = getConfig() const colorProfile = config.get('core.forceColorProfile') if (colorProfile) { - app.commandLine.appendSwitch('force-color-profile', colorProfile) + app.commandLine.appendSwitch('force-color-profile', colorProfile) } if (handleStartupEventWithSquirrel()) { From 266e0111b8a43b2e0138ef047c3f851d3f94d3f3 Mon Sep 17 00:00:00 2001 From: Jason Rudolph Date: Fri, 1 Jun 2018 15:33:28 -0400 Subject: [PATCH 6/8] =?UTF-8?q?=E2=98=A0=E2=98=95=20Decaffienate=20ScopeDe?= =?UTF-8?q?scriptor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Oddly, I expect this to resolve the CI failure seen in https://travis-ci.org/atom/atom/builds/386819124#L1200. --- src/scope-descriptor.coffee | 63 ----------------------------- src/scope-descriptor.js | 80 +++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 63 deletions(-) delete mode 100644 src/scope-descriptor.coffee create mode 100644 src/scope-descriptor.js diff --git a/src/scope-descriptor.coffee b/src/scope-descriptor.coffee deleted file mode 100644 index f1070f277..000000000 --- a/src/scope-descriptor.coffee +++ /dev/null @@ -1,63 +0,0 @@ -# Extended: Wraps an {Array} of `String`s. The Array describes a path from the -# root of the syntax tree to a token including _all_ scope names for the entire -# path. -# -# Methods that take a `ScopeDescriptor` will also accept an {Array} of {String} -# scope names e.g. `['.source.js']`. -# -# You can use `ScopeDescriptor`s to get language-specific config settings via -# {Config::get}. -# -# You should not need to create a `ScopeDescriptor` directly. -# -# * {TextEditor::getRootScopeDescriptor} to get the language's descriptor. -# * {TextEditor::scopeDescriptorForBufferPosition} to get the descriptor at a -# specific position in the buffer. -# * {Cursor::getScopeDescriptor} to get a cursor's descriptor based on position. -# -# See the [scopes and scope descriptor guide](http://flight-manual.atom.io/behind-atom/sections/scoped-settings-scopes-and-scope-descriptors/) -# for more information. -module.exports = -class ScopeDescriptor - @fromObject: (scopes) -> - if scopes instanceof ScopeDescriptor - scopes - else - new ScopeDescriptor({scopes}) - - ### - Section: Construction and Destruction - ### - - # Public: Create a {ScopeDescriptor} object. - # - # * `object` {Object} - # * `scopes` {Array} of {String}s - constructor: ({@scopes}) -> - - # Public: Returns an {Array} of {String}s - getScopesArray: -> @scopes - - getScopeChain: -> - # For backward compatibility, prefix TextMate-style scope names with - # leading dots (e.g. 'source.js' -> '.source.js'). - if @scopes[0]?.includes('.') - result = '' - for scope, i in @scopes - result += ' ' if i > 0 - result += '.' if scope[0] isnt '.' - result += scope - result - else - @scopes.join(' ') - - toString: -> - @getScopeChain() - - isEqual: (other) -> - if @scopes.length isnt other.scopes.length - return false - for scope, i in @scopes - if scope isnt other.scopes[i] - return false - true diff --git a/src/scope-descriptor.js b/src/scope-descriptor.js new file mode 100644 index 000000000..63075e8a1 --- /dev/null +++ b/src/scope-descriptor.js @@ -0,0 +1,80 @@ +// Extended: Wraps an {Array} of `String`s. The Array describes a path from the +// root of the syntax tree to a token including _all_ scope names for the entire +// path. +// +// Methods that take a `ScopeDescriptor` will also accept an {Array} of {String} +// scope names e.g. `['.source.js']`. +// +// You can use `ScopeDescriptor`s to get language-specific config settings via +// {Config::get}. +// +// You should not need to create a `ScopeDescriptor` directly. +// +// * {TextEditor::getRootScopeDescriptor} to get the language's descriptor. +// * {TextEditor::scopeDescriptorForBufferPosition} to get the descriptor at a +// specific position in the buffer. +// * {Cursor::getScopeDescriptor} to get a cursor's descriptor based on position. +// +// See the [scopes and scope descriptor guide](http://flight-manual.atom.io/behind-atom/sections/scoped-settings-scopes-and-scope-descriptors/) +// for more information. +module.exports = +class ScopeDescriptor { + static fromObject (scopes) { + if (scopes instanceof ScopeDescriptor) { + return scopes + } else { + return new ScopeDescriptor({scopes}) + } + } + + /* + Section: Construction and Destruction + */ + + // Public: Create a {ScopeDescriptor} object. + // + // * `object` {Object} + // * `scopes` {Array} of {String}s + constructor ({scopes}) { + this.scopes = scopes + } + + // Public: Returns an {Array} of {String}s + getScopesArray () { + return this.scopes + } + + getScopeChain () { + // For backward compatibility, prefix TextMate-style scope names with + // leading dots (e.g. 'source.js' -> '.source.js'). + if (this.scopes[0] != null && this.scopes[0].includes('.')) { + let result = '' + for (let i = 0; i < this.scopes.length; i++) { + const scope = this.scopes[i] + if (i > 0) { result += ' ' } + if (scope[0] !== '.') { result += '.' } + result += scope + } + return result + } else { + return this.scopes.join(' ') + } + } + + toString () { + return this.getScopeChain() + } + + isEqual (other) { + if (this.scopes.length !== other.scopes.length) { + return false + } + for (let i = 0; i < this.scopes.length; i++) { + const scope = this.scopes[i] + if (scope !== other.scopes[i]) { + return false + } + } + return true + } +} From f9ba602c6c9ab41b2fe88980fc52428c4ff60e9b Mon Sep 17 00:00:00 2001 From: Jason Rudolph Date: Fri, 1 Jun 2018 15:54:29 -0400 Subject: [PATCH 7/8] Gracefully handle missing config file https://circleci.com/gh/atom/atom/7630 --- src/main-process/start.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/main-process/start.js b/src/main-process/start.js index 682532998..6daa8675d 100644 --- a/src/main-process/start.js +++ b/src/main-process/start.js @@ -108,12 +108,19 @@ function setupCompileCache () { } function getConfig () { - const configFilePath = fs.existsSync(path.join(process.env.ATOM_HOME, 'config.json')) - ? path.join(process.env.ATOM_HOME, 'config.json') - : path.join(process.env.ATOM_HOME, 'config.cson') - - const configFileData = CSON.readFileSync(configFilePath) const config = new Config() - config.resetUserSettings(configFileData) + + let configFilePath + if (fs.existsSync(path.join(process.env.ATOM_HOME, 'config.json'))) { + configFilePath = path.join(process.env.ATOM_HOME, 'config.json') + } else if (fs.existsSync(path.join(process.env.ATOM_HOME, 'config.cson'))) { + configFilePath = path.join(process.env.ATOM_HOME, 'config.cson') + } + + if (configFilePath) { + const configFileData = CSON.readFileSync(configFilePath) + config.resetUserSettings(configFileData) + } + return config } From c3d38ed36097059b6351a9ed3d6269f79afadcbb Mon Sep 17 00:00:00 2001 From: Jason Rudolph Date: Fri, 1 Jun 2018 16:32:31 -0400 Subject: [PATCH 8/8] Support configuring color profile via settings UI --- src/config-schema.js | 15 +++++++++++++++ src/main-process/start.js | 4 ++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/config-schema.js b/src/config-schema.js index 97a6d16f3..343726d2c 100644 --- a/src/config-schema.js +++ b/src/config-schema.js @@ -355,6 +355,21 @@ const configSchema = { type: 'boolean', default: false, description: 'Experimental: Use the new Tree-sitter parsing system for supported languages.' + }, + colorProfile: { + description: "Specify whether Atom should use the operating system's color profile (recommended) or an alternative color profile.
Changing this setting will require a relaunch of Atom to take effect.", + type: 'string', + default: 'default', + enum: [ + { + value: 'default', + description: 'Use color profile configured in the operating system' + }, + { + value: 'srgb', + description: 'Use sRGB color profile' + } + ] } } }, diff --git a/src/main-process/start.js b/src/main-process/start.js index 6daa8675d..25bc9c00d 100644 --- a/src/main-process/start.js +++ b/src/main-process/start.js @@ -43,8 +43,8 @@ module.exports = function start (resourcePath, startTime) { setupCompileCache() const config = getConfig() - const colorProfile = config.get('core.forceColorProfile') - if (colorProfile) { + const colorProfile = config.get('core.colorProfile') + if (colorProfile && colorProfile !== 'default') { app.commandLine.appendSwitch('force-color-profile', colorProfile) }