hterm 0.8.8.0: Synchronized preferences.
* Add lib.Storage.Local and lib.Storage.Chrome classes to normalize the API
between window.localStorage and chrome.storage.
* Generalize nassh.PreferenceManager profile management code into
lib.PreferenceManager so that other code can easily define child preferences.
* Add preference to override the default color palette.
* Remove session-id code.
TEST=test_harness.html, 66/66 tests passed.
BUG=chromium-os:26284, Custom palette.
Change-Id: Ic90343253dcb2235a61fcec73e21833a68022fe8
Reviewed-on: https://gerrit.chromium.org/gerrit/34237
Reviewed-by: Dmitry Polukhin <dpolukhin@chromium.org>
Reviewed-by: Marius Schilder <mschilder@google.com>
Tested-by: Marius Schilder <mschilder@google.com>
Commit-Ready: Robert Ginda <rginda@chromium.org>
Reviewed-by: Robert Ginda <rginda@chromium.org>
Tested-by: Robert Ginda <rginda@chromium.org>
diff --git a/hterm/js/hterm_terminal.js b/hterm/js/hterm_terminal.js
index 33a85e1..a553395 100644
--- a/hterm/js/hterm_terminal.js
+++ b/hterm/js/hterm_terminal.js
@@ -6,8 +6,8 @@
lib.rtdep('lib.colors', 'lib.PreferenceManager',
'hterm.msg',
- 'hterm.Keyboard', 'hterm.Options', 'hterm.Screen',
- 'hterm.ScrollPort', 'hterm.Size', 'hterm.VT');
+ 'hterm.Keyboard', 'hterm.Options', 'hterm.PreferenceManager',
+ 'hterm.Screen', 'hterm.ScrollPort', 'hterm.Size', 'hterm.VT');
/**
* Constructor for the Terminal class.
@@ -26,12 +26,11 @@
* displayed twice as wide as standard latin characters. This is to support
* CJK (and possibly other character sets).
*
- * @param {string} opt_profileName Optional preference profile name. If not
+ * @param {string} opt_profileId Optional preference profile name. If not
* provided, defaults to 'default'.
*/
-hterm.Terminal = function(opt_profileName) {
- this.profileName_ = null;
- this.setProfile(opt_profileName || 'default');
+hterm.Terminal = function(opt_profileId) {
+ this.profileId_ = null;
// Two screen instances.
this.primaryScreen_ = new hterm.Screen();
@@ -80,15 +79,14 @@
this.cursorNode_ = null;
// These prefs are cached so we don't have to read from local storage with
- // each output and keystroke.
- this.scrollOnOutput_ = this.prefs_.get('scroll-on-output');
- this.scrollOnKeystroke_ = this.prefs_.get('scroll-on-keystroke');
- this.foregroundColor_ = this.prefs_.get('foreground-color');
- this.backgroundColor_ = this.prefs_.get('background-color');
+ // each output and keystroke. They are initialized by the preference manager.
+ this.scrollOnOutput_ = null;
+ this.scrollOnKeystroke_ = null;
+ this.foregroundColor_ = null;
+ this.backgroundColor_ = null;
// Terminal bell sound.
this.bellAudio_ = this.document_.createElement('audio');
- this.bellAudio_.setAttribute('src', this.prefs_.get('audible-bell-sound'));
this.bellAudio_.setAttribute('preload', 'auto');
// Cursor position and attributes saved with DECSC.
@@ -102,9 +100,6 @@
// The VT escape sequence interpreter.
this.vt = new hterm.VT(this);
- this.vt.enable8BitControl = this.prefs_.get('enable-8-bit-control');
- this.vt.maxStringSequence = this.prefs_.get('max-string-sequence');
- this.vt.enableClipboardWrite = this.prefs_.get('enable-clipboard-write');
// The keyboard hander.
this.keyboard = new hterm.Keyboard(this);
@@ -116,15 +111,26 @@
// True if mouse-click-drag should scroll the terminal.
this.enableMouseDragScroll = true;
- this.copyOnSelect = this.prefs_.get('copy-on-select');
+ this.copyOnSelect = null;
this.mousePasteButton = null;
- this.syncMousePasteButton();
this.realizeSize_(80, 24);
this.setDefaultTabStops();
+
+ this.setProfile(opt_profileId || 'default',
+ function() { this.onTerminalReady() }.bind(this));
};
/**
+ * Clients should override this to be notified when the terminal is ready
+ * for use.
+ *
+ * The terminal initialization is asynchronous, and shouldn't be used before
+ * this method is called.
+ */
+hterm.Terminal.prototype.onTerminalReady = function() { };
+
+/**
* Default tab with of 8 to match xterm.
*/
hterm.Terminal.prototype.tabWidth = 8;
@@ -142,297 +148,170 @@
*
* @param {string} newName The name of the preference profile. Forward slash
* characters will be removed from the name.
+ * @param {function} opt_callback Optional callback to invoke when the profile
+ * transition is complete.
*/
-hterm.Terminal.prototype.setProfile = function(profileName) {
- // If we already have a profile selected, we're going to need to re-sync
- // with the new profile.
- var needSync = !!this.profileName_;
+hterm.Terminal.prototype.setProfile = function(profileId, opt_callback) {
+ this.profileId_ = profileId.replace(/\//g, '');
- this.profileName_ = profileName.replace(/\//g, '');
+ var terminal = this;
- this.prefs_ = new lib.PreferenceManager(
- '/hterm/prefs/profiles/' + this.profileName_);
+ if (this.prefs_)
+ this.prefs_.deactivate();
- var self = this;
- this.prefs_.definePreferences
- ([
- /**
- * Set whether the alt key acts as a meta key or as a distinct alt key.
- */
- ['alt-is-meta', false, function(v) {
- self.keyboard.altIsMeta = v;
+ this.prefs_ = new hterm.PreferenceManager(this.profileId_);
+ this.prefs_.addObservers(null, {
+ 'alt-is-meta': function(v) {
+ terminal.keyboard.altIsMeta = v;
+ },
+
+ 'alt-sends-what': function(v) {
+ if (!/^(escape|8-bit|browser-key)$/.test(v))
+ v = 'escape';
+
+ terminal.keyboard.altSendsWhat = v;
+ },
+
+ 'audible-bell-sound': function(v) {
+ terminal.bellAudio_.setAttribute('src', v);
+ },
+
+ 'background-color': function(v) {
+ terminal.setBackgroundColor(v);
+ },
+
+ 'background-image': function(v) {
+ terminal.scrollPort_.setBackgroundImage(v);
+ },
+
+ 'background-size': function(v) {
+ terminal.scrollPort_.setBackgroundSize(v);
+ },
+
+ 'background-position': function(v) {
+ terminal.scrollPort_.setBackgroundPosition(v);
+ },
+
+ 'backspace-sends-backspace': function(v) {
+ terminal.keyboard.backspaceSendsBackspace = v;
+ },
+
+ 'cursor-blink': function(v) {
+ terminal.setCursorBlink(!!v);
+ },
+
+ 'cursor-color': function(v) {
+ terminal.setCursorColor(v);
+ },
+
+ 'color-palette-overrides': function(v) {
+ if (!(v == null || v instanceof Object || v instanceof Array)) {
+ console.warn('Preference color-palette-overrides is not an array or ' +
+ 'object: ' + v);
+ return;
}
- ],
- /**
- * Controls how the alt key is handled.
- *
- * escape....... Send an ESC prefix.
- * 8-bit........ Add 128 to the unshifted character as in xterm.
- * browser-key.. Wait for the keypress event and see what the browser says.
- * (This won't work well on platforms where the browser
- * performs a default action for some alt sequences.)
- */
- ['alt-sends-what', 'escape', function(v) {
- if (!/^(escape|8-bit|browser-key)$/.test(v))
- v = 'escape';
+ lib.colors.colorPalette = lib.colors.stockColorPalette.concat();
- self.keyboard.altSendsWhat = v;
+ if (v) {
+ for (var key in v) {
+ var i = parseInt(key);
+ if (isNaN(i) || i < 0 || i > 255) {
+ console.log('Invalid value in palette: ' + key + ': ' + v[key]);
+ continue;
+ }
+
+ if (v[i]) {
+ var rgb = lib.colors.normalizeCSS(v[i]);
+ if (rgb)
+ lib.colors.colorPalette[i] = rgb;
+ }
+ }
}
- ],
- /**
- * Terminal bell sound. Empty string for no audible bell.
- */
- ['audible-bell-sound', '../audio/bell.ogg', function(v) {
- self.bellAudio_.setAttribute('src', v);
- }
- ],
+ terminal.primaryScreen_.textAttributes.resetColorPalette()
+ terminal.alternateScreen_.textAttributes.resetColorPalette();
+ },
- /**
- * The background color for text with no other color attributes.
- */
- ['background-color', 'rgb(16, 16, 16)', function(v) {
- self.setBackgroundColor(v);
- }
- ],
+ 'copy-on-select': function(v) {
+ terminal.copyOnSelect = !!v;
+ },
- /**
- * The background image.
- */
- ['background-image', '',
- function(v) {
- self.scrollPort_.setBackgroundImage(v);
- }
- ],
+ 'enable-8-bit-control': function(v) {
+ terminal.vt.enable8BitControl = !!v;
+ },
- /**
- * The background image size,
- *
- * Defaults to none.
- */
- ['background-size', '', function(v) {
- self.scrollPort_.setBackgroundSize(v);
- }
- ],
+ 'enable-bold': function(v) {
+ terminal.syncBoldSafeState();
+ },
- /**
- * The background image position,
- *
- * Defaults to none.
- */
- ['background-position', '', function(v) {
- self.scrollPort_.setBackgroundPosition(v);
- }
- ],
+ 'enable-clipboard-write': function(v) {
+ terminal.vt.enableClipboardWrite = !!v;
+ },
- /**
- * If true, the backspace should send BS ('\x08', aka ^H). Otherwise
- * the backspace key should send '\x7f'.
- */
- ['backspace-sends-backspace', false, function(v) {
- self.keyboard.backspaceSendsBackspace = v;
- }
- ],
+ 'font-family': function(v) {
+ terminal.syncFontFamily();
+ },
- /**
- * Whether or not to close the window when the command exits.
- */
- ['close-on-exit', true, null],
+ 'font-size': function(v) {
+ terminal.setFontSize(v);
+ },
- /**
- * Whether or not to blink the cursor by default.
- */
- ['cursor-blink', false, function(v) {
- self.setCursorBlink(!!v);
- }
- ],
+ 'font-smoothing': function(v) {
+ terminal.syncFontFamily();
+ },
- /**
- * The color of the visible cursor.
- */
- ['cursor-color', 'rgba(255,0,0,0.5)', function(v) {
- self.setCursorColor(v);
- }
- ],
+ 'foreground-color': function(v) {
+ terminal.setForegroundColor(v);
+ },
- /**
- * Automatically copy mouse selection to the clipboard.
- */
- ['copy-on-select', true, function(v) {
- self.copyOnSelect = !!v;
- }
- ],
+ 'home-keys-scroll': function(v) {
+ terminal.keyboard.homeKeysScroll = v;
+ },
- /**
- * True to enable 8-bit control characters, false to ignore them.
- *
- * We'll respect the two-byte versions of these control characters
- * regardless of this setting.
- */
- ['enable-8-bit-control', false, function(v) {
- self.vt.enable8BitControl = !!v;
- }
- ],
+ 'max-string-sequence': function(v) {
+ terminal.vt.maxStringSequence = v;
+ },
- /**
- * True if we should use bold weight font for text with the bold/bright
- * attribute. False to use bright colors only. Null to autodetect.
- */
- ['enable-bold', null, function(v) {
- self.syncBoldSafeState();
- }
- ],
+ 'meta-sends-escape': function(v) {
+ terminal.keyboard.metaSendsEscape = v;
+ },
- /**
- * Allow the host to write directly to the system clipboard.
- */
- ['enable-clipboard-notice', true, null],
+ 'mouse-cell-motion-trick': function(v) {
+ terminal.vt.setMouseCellMotionTrick(v);
+ },
- /**
- * Allow the host to write directly to the system clipboard.
- */
- ['enable-clipboard-write', true, function(v) {
- self.vt.enableClipboardWrite = !!v;
- }
- ],
+ 'mouse-paste-button': function(v) {
+ terminal.syncMousePasteButton();
+ },
- /**
- * Default font family for the terminal text.
- */
- ['font-family', ('"DejaVu Sans Mono", "Everson Mono", ' +
- 'FreeMono, "Menlo", "Terminal", ' +
- 'monospace'),
- function(v) { self.syncFontFamily() }
- ],
+ 'scroll-on-keystroke': function(v) {
+ terminal.scrollOnKeystroke_ = v;
+ },
- /**
- * The default font size in pixels.
- */
- ['font-size', 15, function(v) {
- self.setFontSize(v);
- }
- ],
+ 'scroll-on-output': function(v) {
+ terminal.scrollOnOutput_ = v;
+ },
- /**
- * Anti-aliasing.
- */
- ['font-smoothing', 'antialiased',
- function(v) { self.syncFontFamily() }
- ],
+ 'scrollbar-visible': function(v) {
+ terminal.setScrollbarVisible(v);
+ },
- /**
- * The foreground color for text with no other color attributes.
- */
- ['foreground-color', 'rgb(240, 240, 240)', function(v) {
- self.setForegroundColor(v);
- }
- ],
+ 'shift-insert-paste': function(v) {
+ terminal.keyboard.shiftInsertPaste = v;
+ },
- /**
- * If true, home/end will control the terminal scrollbar and shift home/end
- * will send the VT keycodes. If false then home/end sends VT codes and
- * shift home/end scrolls.
- */
- ['home-keys-scroll', false, function(v) {
- self.keyboard.homeKeysScroll = v;
- }
- ],
+ 'page-keys-scroll': function(v) {
+ terminal.keyboard.pageKeysScroll = v;
+ }
+ });
- /**
- * Max length of a DCS, OSC, PM, or APS sequence before we give up and
- * ignore the code.
- */
- ['max-string-sequence', 100000, function(v) {
- self.vt.maxStringSequence = v;
- }
- ],
-
- /**
- * Set whether the meta key sends a leading escape or not.
- */
- ['meta-sends-escape', true, function(v) {
- self.keyboard.metaSendsEscape = v;
- }
- ],
-
- /**
- * Set whether we should treat DEC mode 1002 (mouse cell motion tracking)
- * as if it were 1000 (mouse click tracking).
- *
- * This makes it possible to use vi's ":set mouse=a" mode without losing
- * access to the system text selection mechanism.
- */
- ['mouse-cell-motion-trick', false, function(v) {
- self.vt.setMouseCellMotionTrick(v);
- }
- ],
-
- /**
- * Mouse paste button, or null to autodetect.
- *
- * For autodetect, we'll try to enable middle button paste for non-X11
- * platforms.
- *
- * On X11 we move it to button 3, but that'll probably be a context menu
- * in the future.
- */
- ['mouse-paste-button', null, function(v) {
- self.syncMousePasteButton();
- }
- ],
-
- /**
- * If true, scroll to the bottom on any keystroke.
- */
- ['scroll-on-keystroke', true, function(v) {
- self.scrollOnKeystroke_ = v;
- }
- ],
-
- /**
- * If true, scroll to the bottom on terminal output.
- */
- ['scroll-on-output', false, function(v) {
- self.scrollOnOutput_ = v;
- }
- ],
-
- /**
- * The vertical scrollbar mode.
- */
- ['scrollbar-visible', true, function(v) {
- self.setScrollbarVisible(v);
- }
- ],
-
- /**
- * Shift + Insert pastes if true, sent to host if false.
- */
- ['shift-insert-paste', true, function(v) {
- self.keyboard.shiftInsertPaste = v;
- }
- ],
-
- /**
- * The default environment variables.
- */
- ['environment', {TERM: 'xterm-256color'}, null],
-
- /**
- * If true, page up/down will control the terminal scrollbar and shift
- * page up/down will send the VT keycodes. If false then page up/down
- * sends VT codes and shift page up/down scrolls.
- */
- ['page-keys-scroll', false, function(v) {
- self.keyboard.pageKeysScroll = v;
- }
- ],
-
- ]);
-
- if (needSync)
+ this.prefs_.readStorage(function() {
this.prefs_.notifyAll();
+
+ if (opt_callback)
+ opt_callback();
+ }.bind(this));
};
@@ -470,6 +349,10 @@
*/
hterm.Terminal.prototype.setBackgroundColor = function(color) {
this.backgroundColor_ = lib.colors.normalizeCSS(color);
+ this.primaryScreen_.textAttributes.setDefaults(
+ this.foregroundColor_, this.backgroundColor_);
+ this.alternateScreen_.textAttributes.setDefaults(
+ this.foregroundColor_, this.backgroundColor_);
this.scrollPort_.setBackgroundColor(color);
};
@@ -491,6 +374,10 @@
*/
hterm.Terminal.prototype.setForegroundColor = function(color) {
this.foregroundColor_ = lib.colors.normalizeCSS(color);
+ this.primaryScreen_.textAttributes.setDefaults(
+ this.foregroundColor_, this.backgroundColor_);
+ this.alternateScreen_.textAttributes.setDefaults(
+ this.foregroundColor_, this.backgroundColor_);
this.scrollPort_.setForegroundColor(color);
};