|
|
@ -2,21 +2,77 @@ |
|
|
|
import { Disposable, workspace } from 'vscode'; |
|
|
|
import { Logger } from './logger'; |
|
|
|
|
|
|
|
interface ConfigurationInspection { |
|
|
|
key: string; |
|
|
|
defaultValue?: string; |
|
|
|
globalValue?: string; |
|
|
|
workspaceValue?: string; |
|
|
|
} |
|
|
|
|
|
|
|
enum SettingLocation { |
|
|
|
workspace, |
|
|
|
global, |
|
|
|
default |
|
|
|
} |
|
|
|
|
|
|
|
class RenderWhitespaceConfiguration { |
|
|
|
|
|
|
|
constructor(public inspection: ConfigurationInspection) { } |
|
|
|
|
|
|
|
get location(): SettingLocation { |
|
|
|
if (this.inspection.workspaceValue) return SettingLocation.workspace; |
|
|
|
if (this.inspection.globalValue) return SettingLocation.global; |
|
|
|
return SettingLocation.default; |
|
|
|
} |
|
|
|
|
|
|
|
get overrideRequired() { |
|
|
|
return this.value != null && this.value !== 'none'; |
|
|
|
} |
|
|
|
|
|
|
|
get value(): string { |
|
|
|
return this.inspection.workspaceValue || this.inspection.globalValue || this.inspection.defaultValue; |
|
|
|
} |
|
|
|
|
|
|
|
update(replacement: ConfigurationInspection): boolean { |
|
|
|
let override = false; |
|
|
|
|
|
|
|
switch (this.location) { |
|
|
|
case SettingLocation.workspace: |
|
|
|
this.inspection.defaultValue = replacement.defaultValue; |
|
|
|
this.inspection.globalValue = replacement.globalValue; |
|
|
|
if (replacement.workspaceValue !== 'none') { |
|
|
|
this.inspection.workspaceValue = replacement.workspaceValue; |
|
|
|
override = true; |
|
|
|
} |
|
|
|
break; |
|
|
|
case SettingLocation.global: |
|
|
|
this.inspection.defaultValue = replacement.defaultValue; |
|
|
|
this.inspection.workspaceValue = replacement.workspaceValue; |
|
|
|
if (replacement.globalValue !== 'none') { |
|
|
|
this.inspection.globalValue = replacement.globalValue; |
|
|
|
override = true; |
|
|
|
} |
|
|
|
break; |
|
|
|
case SettingLocation.default: |
|
|
|
this.inspection.globalValue = replacement.globalValue; |
|
|
|
this.inspection.workspaceValue = replacement.workspaceValue; |
|
|
|
if (replacement.defaultValue !== 'none') { |
|
|
|
this.inspection.defaultValue = replacement.defaultValue; |
|
|
|
override = true; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
return override; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
export class WhitespaceController extends Disposable { |
|
|
|
|
|
|
|
private _configuration: RenderWhitespaceConfiguration; |
|
|
|
private _count: number = 0; |
|
|
|
private _disposable: Disposable; |
|
|
|
private _disposed: boolean = false; |
|
|
|
private _ignoreNextConfigChange: boolean = false; |
|
|
|
private _renderWhitespace: string; |
|
|
|
private _renderWhitespaceLocation: SettingLocation = SettingLocation.default; |
|
|
|
private _requiresOverride: boolean; |
|
|
|
|
|
|
|
constructor() { |
|
|
|
super(() => this.dispose()); |
|
|
@ -30,10 +86,10 @@ export class WhitespaceController extends Disposable { |
|
|
|
this._onConfigurationChanged(); |
|
|
|
} |
|
|
|
|
|
|
|
dispose() { |
|
|
|
async dispose() { |
|
|
|
this._disposed = true; |
|
|
|
if (this._count !== 0) { |
|
|
|
this._restoreWhitespace(); |
|
|
|
await this._restoreWhitespace(); |
|
|
|
this._count = 0; |
|
|
|
} |
|
|
|
} |
|
|
@ -41,75 +97,56 @@ export class WhitespaceController extends Disposable { |
|
|
|
private _onConfigurationChanged() { |
|
|
|
if (this._disposed) return; |
|
|
|
|
|
|
|
if (this._ignoreNextConfigChange) { |
|
|
|
this._ignoreNextConfigChange = false; |
|
|
|
Logger.log(`Whitespace changed; ignored`); |
|
|
|
const inspection = workspace.getConfiguration('editor').inspect<string>('renderWhitespace'); |
|
|
|
|
|
|
|
if (!this._count) { |
|
|
|
this._configuration = new RenderWhitespaceConfiguration(inspection); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
const config = workspace.getConfiguration('editor'); |
|
|
|
const inspection = config.inspect<string>('renderWhitespace'); |
|
|
|
|
|
|
|
if (inspection.workspaceValue) { |
|
|
|
this._renderWhitespace = inspection.workspaceValue; |
|
|
|
this._renderWhitespaceLocation = SettingLocation.workspace; |
|
|
|
} |
|
|
|
else if (inspection.globalValue) { |
|
|
|
this._renderWhitespace = inspection.globalValue; |
|
|
|
this._renderWhitespaceLocation = SettingLocation.global; |
|
|
|
} |
|
|
|
else { |
|
|
|
this._renderWhitespace = inspection.defaultValue; |
|
|
|
this._renderWhitespaceLocation = SettingLocation.default; |
|
|
|
} |
|
|
|
|
|
|
|
Logger.log(`Whitespace changed; renderWhitespace=${this._renderWhitespace}, location=${this._renderWhitespaceLocation}`); |
|
|
|
this._requiresOverride = !(this._renderWhitespace == null || this._renderWhitespace === 'none'); |
|
|
|
if (this._requiresOverride) { |
|
|
|
if (this._count !== 0) { |
|
|
|
// Since we were currently overriding whitespace, re-override
|
|
|
|
this._overrideWhitespace(); |
|
|
|
} |
|
|
|
if (this._configuration.update(inspection)) { |
|
|
|
// Since we were currently overriding whitespace, re-override
|
|
|
|
setTimeout(() => this._overrideWhitespace(), 1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
override() { |
|
|
|
async override() { |
|
|
|
if (this._disposed) return; |
|
|
|
|
|
|
|
Logger.log(`Request whitespace override; count=${this._count}`); |
|
|
|
if (this._count === 0 && this._requiresOverride) { |
|
|
|
this._ignoreNextConfigChange = true; |
|
|
|
this._count++; |
|
|
|
if (this._count === 1 && this._configuration.overrideRequired) { |
|
|
|
// Override whitespace (turn off)
|
|
|
|
this._overrideWhitespace(); |
|
|
|
await this._overrideWhitespace(); |
|
|
|
// Add a delay to give the editor time to turn off the whitespace
|
|
|
|
await new Promise((resolve, reject) => setTimeout(resolve, 250)); |
|
|
|
} |
|
|
|
this._count++; |
|
|
|
} |
|
|
|
|
|
|
|
private _overrideWhitespace() { |
|
|
|
private async _overrideWhitespace() { |
|
|
|
Logger.log(`Override whitespace`); |
|
|
|
const config = workspace.getConfiguration('editor'); |
|
|
|
config.update('renderWhitespace', 'none', this._renderWhitespaceLocation === SettingLocation.global); |
|
|
|
return config.update('renderWhitespace', 'none', this._configuration.location === SettingLocation.global); |
|
|
|
} |
|
|
|
|
|
|
|
restore() { |
|
|
|
async restore() { |
|
|
|
if (this._disposed || this._count === 0) return; |
|
|
|
|
|
|
|
Logger.log(`Request whitespace restore; count=${this._count}`); |
|
|
|
this._count--; |
|
|
|
if (this._count === 0 && this._requiresOverride) { |
|
|
|
if (this._count === 0 && this._configuration.overrideRequired) { |
|
|
|
// restore whitespace
|
|
|
|
this._restoreWhitespace(); |
|
|
|
await this._restoreWhitespace(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private _restoreWhitespace() { |
|
|
|
private async _restoreWhitespace() { |
|
|
|
Logger.log(`Restore whitespace`); |
|
|
|
const config = workspace.getConfiguration('editor'); |
|
|
|
config.update('renderWhitespace', |
|
|
|
this._renderWhitespaceLocation === SettingLocation.default |
|
|
|
return config.update('renderWhitespace', |
|
|
|
this._configuration.location === SettingLocation.default |
|
|
|
? undefined |
|
|
|
: this._renderWhitespace, |
|
|
|
this._renderWhitespaceLocation === SettingLocation.global); |
|
|
|
: this._configuration.value, |
|
|
|
this._configuration.location === SettingLocation.global); |
|
|
|
} |
|
|
|
} |