xterm
[VSoRC/.git] / node_modules / xterm / src / common / services / OptionsService.ts
1 /**
2  * Copyright (c) 2019 The xterm.js authors. All rights reserved.
3  * @license MIT
4  */
5
6 import { IOptionsService, ITerminalOptions, IPartialTerminalOptions } from 'common/services/Services';
7 import { EventEmitter, IEvent } from 'common/EventEmitter';
8 import { isMac } from 'common/Platform';
9 import { clone } from 'common/Clone';
10
11 // Source: https://freesound.org/people/altemark/sounds/45759/
12 // This sound is released under the Creative Commons Attribution 3.0 Unported
13 // (CC BY 3.0) license. It was created by 'altemark'. No modifications have been
14 // made, apart from the conversion to base64.
15 export const DEFAULT_BELL_SOUND = 'data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4LjMyLjEwNAAAAAAAAAAAAAAA//tQxAADB8AhSmxhIIEVCSiJrDCQBTcu3UrAIwUdkRgQbFAZC1CQEwTJ9mjRvBA4UOLD8nKVOWfh+UlK3z/177OXrfOdKl7pyn3Xf//WreyTRUoAWgBgkOAGbZHBgG1OF6zM82DWbZaUmMBptgQhGjsyYqc9ae9XFz280948NMBWInljyzsNRFLPWdnZGWrddDsjK1unuSrVN9jJsK8KuQtQCtMBjCEtImISdNKJOopIpBFpNSMbIHCSRpRR5iakjTiyzLhchUUBwCgyKiweBv/7UsQbg8isVNoMPMjAAAA0gAAABEVFGmgqK////9bP/6XCykxBTUUzLjEwMKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq';
16
17 // TODO: Freeze?
18 export const DEFAULT_OPTIONS: ITerminalOptions = Object.freeze({
19   cols: 80,
20   rows: 24,
21   cursorBlink: false,
22   cursorStyle: 'block',
23   bellSound:  DEFAULT_BELL_SOUND,
24   bellStyle: 'none',
25   drawBoldTextInBrightColors: true,
26   fastScrollModifier: 'alt',
27   fastScrollSensitivity: 5,
28   fontFamily: 'courier-new, courier, monospace',
29   fontSize: 15,
30   fontWeight: 'normal',
31   fontWeightBold: 'bold',
32   lineHeight: 1.0,
33   letterSpacing: 0,
34   logLevel: 'info',
35   scrollback: 1000,
36   scrollSensitivity: 1,
37   screenReaderMode: false,
38   macOptionIsMeta: false,
39   macOptionClickForcesSelection: false,
40   disableStdin: false,
41   allowTransparency: false,
42   tabStopWidth: 8,
43   theme: {},
44   rightClickSelectsWord: isMac,
45   rendererType: 'canvas',
46   windowsMode: false,
47
48   convertEol: false,
49   termName: 'xterm',
50   screenKeys: false,
51   cancelEvents: false,
52   useFlowControl: false,
53   wordSeparator: ' ()[]{}\',:;"'
54 });
55
56 /**
57  * The set of options that only have an effect when set in the Terminal constructor.
58  */
59 const CONSTRUCTOR_ONLY_OPTIONS = ['cols', 'rows'];
60
61 export class OptionsService implements IOptionsService {
62   serviceBrand: any;
63
64   public options: ITerminalOptions;
65
66   private _onOptionChange = new EventEmitter<string>();
67   public get onOptionChange(): IEvent<string> { return this._onOptionChange.event; }
68
69   constructor(options: IPartialTerminalOptions) {
70     this.options = clone(DEFAULT_OPTIONS);
71     Object.keys(options).forEach(k => {
72       if (k in this.options) {
73         const newValue = options[k as keyof IPartialTerminalOptions] as any;
74         this.options[k] = newValue;
75       }
76     });
77   }
78
79   public setOption(key: string, value: any): void {
80     if (!(key in DEFAULT_OPTIONS)) {
81       throw new Error('No option with key "' + key + '"');
82     }
83     if (CONSTRUCTOR_ONLY_OPTIONS.indexOf(key) !== -1) {
84       throw new Error(`Option "${key}" can only be set in the constructor`);
85     }
86     if (this.options[key] === value) {
87       return;
88     }
89
90     value = this._sanitizeAndValidateOption(key, value);
91
92     // Don't fire an option change event if they didn't change
93     if (this.options[key] === value) {
94       return;
95     }
96
97     this.options[key] = value;
98     this._onOptionChange.fire(key);
99   }
100
101   private _sanitizeAndValidateOption(key: string, value: any): any {
102     switch (key) {
103       case 'bellStyle':
104       case 'cursorStyle':
105       case 'fontWeight':
106       case 'fontWeightBold':
107       case 'rendererType':
108       case 'wordSeparator':
109         if (!value) {
110           value = DEFAULT_OPTIONS[key];
111         }
112         break;
113       case 'lineHeight':
114       case 'tabStopWidth':
115         if (value < 1) {
116           throw new Error(`${key} cannot be less than 1, value: ${value}`);
117         }
118         break;
119       case 'scrollback':
120         value = Math.min(value, 4294967295);
121         if (value < 0) {
122           throw new Error(`${key} cannot be less than 0, value: ${value}`);
123         }
124         break;
125       case 'fastScrollSensitivity':
126       case 'scrollSensitivity':
127         if (value <= 0) {
128           throw new Error(`${key} cannot be less than or equal to 0, value: ${value}`);
129         }
130         break;
131     }
132     return value;
133   }
134
135   public getOption(key: string): any {
136     if (!(key in DEFAULT_OPTIONS)) {
137       throw new Error(`No option with key "${key}"`);
138     }
139     return this.options[key];
140   }
141 }