Skip to content

Commit

Permalink
Fixes nodejs#555.
Browse files Browse the repository at this point in the history
  • Loading branch information
iizukanao committed Mar 12, 2013
1 parent 43c1830 commit 0583609
Showing 1 changed file with 112 additions and 15 deletions.
127 changes: 112 additions & 15 deletions lib/readline.js
Expand Up @@ -148,15 +148,8 @@ Interface.prototype.__defineGetter__('columns', function() {
return this.output.columns || Infinity;
});

Interface.prototype.setPrompt = function(prompt, length) {
Interface.prototype.setPrompt = function(prompt) {
this._prompt = prompt;
if (length) {
this._promptLength = length;
} else {
var lines = prompt.split(/[\r\n]/);
var lastLine = lines[lines.length - 1];
this._promptLength = lastLine.length;
}
};


Expand Down Expand Up @@ -224,9 +217,9 @@ Interface.prototype._refreshLine = function() {

// line length
var line = this._prompt + this.line;
var lineLength = line.length;
var lineCols = lineLength % columns;
var lineRows = (lineLength - lineCols) / columns;
var dispPos = this._getDisplayPos(line);
var lineCols = dispPos.cols;
var lineRows = dispPos.rows;

// cursor position
var cursorPos = this._getCursorPos();
Expand Down Expand Up @@ -558,13 +551,40 @@ Interface.prototype._historyPrev = function() {
}
};

// Returns the last character's display position of the given string
Interface.prototype._getDisplayPos = function(str) {
var offset = 0;
var col = this.columns;
for (var i = 0, len = str.length; i < len; i++) {
if (isFullWidthCharCode(str.charCodeAt(i))) {
if ((offset + 1) % col === 0) {
offset++;
}
offset += 2;
} else {
offset++;
}
}
var cols = offset % col;
var rows = (offset - cols) / col;
return {cols: cols, rows: rows};
};

// Returns current cursor's position and line
Interface.prototype._getCursorPos = function() {
var columns = this.columns;
var cursorPos = this.cursor + this._promptLength;
var cols = cursorPos % columns;
var rows = (cursorPos - cols) / columns;
var strBeforeCursor = this._prompt + this.line.substring(0, this.cursor);
var dispPos = this._getDisplayPos(strBeforeCursor);
var cols = dispPos.cols;
var rows = dispPos.rows;
// If the cursor is on a full-width character which steps over the line,
// move the cursor to the beginning of the next line.
if (cols + 1 === columns &&
this.cursor < this.line.length &&
isFullWidthCharCode(this.line.charCodeAt(this.cursor))) {
rows++;
cols = 0;
}
return {cols: cols, rows: rows};
};

Expand All @@ -584,7 +604,18 @@ Interface.prototype._moveCursor = function(dx) {

// check if cursors are in the same line
if (oldPos.rows === newPos.rows) {
exports.moveCursor(this.output, this.cursor - oldcursor, 0);
var diffCursor = this.cursor - oldcursor;
var diffWidth;
if (diffCursor < 0) {
diffWidth = -getStringWidth(
this.line.substring(this.cursor, oldcursor)
);
} else if (diffCursor > 0) {
diffWidth = getStringWidth(
this.line.substring(this.cursor, oldcursor)
);
}
exports.moveCursor(this.output, diffWidth, 0);
this.prevRows = newPos.rows;
} else {
this._refreshLine();
Expand Down Expand Up @@ -1161,3 +1192,69 @@ function clearScreenDown(stream) {
stream.write('\x1b[0J');
}
exports.clearScreenDown = clearScreenDown;


/**
* Returns the number of columns required to display the given string.
*/

function getStringWidth(str) {
var width = 0;
for (var i = 0, len = str.length; i < len; i++) {
if (isFullWidthCharCode(str.charCodeAt(i))) {
width += 2;
} else {
width++;
}
}
return width;
}
exports.getStringWidth = getStringWidth;


/**
* Returns true if the character represented by a given
* Unicode code point is full-width. Otherwise returns false.
*/

function isFullWidthCharCode(code) {
if (isNaN(code)) {
return false;
}

// Code points are derived from:
// http://www.unicode.org/Public/UNIDATA/EastAsianWidth.txt
if (code >= 0x1100 && (
code <= 0x115f || // Hangul Jamo
0x2329 === code || // LEFT-POINTING ANGLE BRACKET
0x232a === code || // RIGHT-POINTING ANGLE BRACKET
// CJK Radicals Supplement .. Enclosed CJK Letters and Months
(0x2e80 <= code && code <= 0x3247 && code !== 0x303f) ||
// Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A
0x3250 <= code && code <= 0x4dbf ||
// CJK Unified Ideographs .. Yi Radicals
0x4e00 <= code && code <= 0xa4c6 ||
// Hangul Jamo Extended-A
0xa960 <= code && code <= 0xa97c ||
// Hangul Syllables
0xac00 <= code && code <= 0xd7a3 ||
// CJK Compatibility Ideographs
0xf900 <= code && code <= 0xfaff ||
// Vertical Forms
0xfe10 <= code && code <= 0xfe19 ||
// CJK Compatibility Forms .. Small Form Variants
0xfe30 <= code && code <= 0xfe6b ||
// Halfwidth and Fullwidth Forms
0xff01 <= code && code <= 0xff60 ||
0xffe0 <= code && code <= 0xffe6 ||
// Kana Supplement
0x1b000 <= code && code <= 0x1b001 ||
// Enclosed Ideographic Supplement
0x1f200 <= code && code <= 0x1f251 ||
// CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane
0x20000 <= code && code <= 0x3fffd)) {
return true;
}
return false;
}
exports.isFullWidthCharCode = isFullWidthCharCode;

0 comments on commit 0583609

Please sign in to comment.