caesar-parser
Advanced tools
Comparing version 0.2.2 to 0.2.3
275
lib/Doc.js
@@ -7,2 +7,4 @@ 'use strict'; | ||
var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })(); | ||
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
@@ -20,8 +22,19 @@ | ||
var _utils = require('./utils'); | ||
var emptyStack = new _immutable.List(); | ||
var count = 0; | ||
var __count = 0; | ||
/** | ||
* @typedef {object} Pos | ||
* @property {number} row - 行 | ||
* @property {number} col - 列 | ||
*/ | ||
/** | ||
* parser document | ||
*/ | ||
var Doc = (function () { | ||
/** | ||
* @param {string|array}code | ||
* @param {string|array} code | ||
*/ | ||
@@ -38,4 +51,5 @@ | ||
code = typeof code === 'string' ? code.split(_constants.ENDED_REG) : code; | ||
this._emptyLine = this._createLine(''); | ||
code = code.map(function (content) { | ||
return _this._createRow({ content: content }); | ||
return _this._createLine(content); | ||
}); | ||
@@ -45,20 +59,50 @@ this._code = new _immutable2['default'].List(code); | ||
/** | ||
* 获取行 | ||
* @param {Row} row | ||
* @returns {Line} | ||
*/ | ||
_createClass(Doc, [{ | ||
key: 'getRow', | ||
value: function getRow(row) { | ||
key: 'getLine', | ||
value: function getLine(row) { | ||
return this._code.get(row); | ||
} | ||
/** | ||
* @param {Row} row | ||
* @returns {string} | ||
*/ | ||
}, { | ||
key: 'getRowContent', | ||
value: function getRowContent(row) { | ||
key: 'getLineContent', | ||
value: function getLineContent(row) { | ||
return this._code.getIn([row, 'content']); | ||
} | ||
/** | ||
* @param {string} content | ||
* @param {object} [addition] | ||
* { | ||
* {array} styleStack | ||
* {array} indentStack | ||
* {Context} context | ||
* } | ||
* @returns {Line} | ||
* @private | ||
*/ | ||
}, { | ||
key: '_createRow', | ||
value: function _createRow(_ref) { | ||
var content = _ref.content; | ||
var styleStack = _ref.styleStack; | ||
var indentStack = _ref.indentStack; | ||
var context = _ref.context; | ||
key: '_createLine', | ||
value: function _createLine(content) { | ||
var addition = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
var styleStack = addition.styleStack; | ||
var context = addition.context; | ||
var indentStack = addition.indentStack; | ||
/** | ||
* @typedef {Immutable.Map} Line | ||
* @property {string} content - 行 | ||
* @property {number} id - id, 唯一 | ||
* @property {Immutable.List} styleStack - highlight样式 | ||
* @property {Immutable.List} indentStack - 缩进样式 | ||
*/ | ||
var line = new _immutable.Map({ | ||
@@ -70,3 +114,3 @@ content: content !== undefined ? content : '', | ||
// 没创建的行都会有唯一的标记 | ||
line.id = count++; | ||
line.id = __count++; | ||
// context 不保存到Map里以免影响hashCode判断 | ||
@@ -76,19 +120,200 @@ line.context = context; | ||
} | ||
/** | ||
* @param {Row} row | ||
* @param {string|object} data | ||
* @return {Doc} | ||
*/ | ||
}, { | ||
key: 'updateRow', | ||
value: function updateRow(index) { | ||
key: 'updateLine', | ||
value: function updateLine(row) { | ||
var data = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
var oldRow = this.getRow(index); | ||
var oldRow = this.getLine(row); | ||
data = typeof data === 'string' ? { content: data } : data; | ||
var oldContent = oldRow.get('content'); | ||
data.content = data.content === undefined ? oldContent : data.content; | ||
var newRow = this._createRow(data); | ||
var newContent = data.content === undefined ? oldContent : data.content; | ||
var newRow = this._createLine(newContent, data); | ||
// 如果hashCode没变, 则只更新context | ||
if (oldRow.hashCode() === newRow.hashCode()) { | ||
oldRow.context = newRow.context === undefined ? oldRow.context : newRow.context; | ||
return this._code; | ||
return this; | ||
} | ||
return this._code.set(index, newRow); | ||
this._code = this._code.set(row, newRow); | ||
return this; | ||
} | ||
/** | ||
* @param {Row} row | ||
* @return {Line|null} | ||
*/ | ||
}, { | ||
key: 'delLine', | ||
value: function delLine(row) { | ||
return this.delLines(row, row).get(0); | ||
} | ||
/** | ||
* @param {Row} startRow | ||
* @param {Row} endRow | ||
* @return {List<Line>} delLines | ||
*/ | ||
}, { | ||
key: 'delLines', | ||
value: function delLines(startRow, endRow) { | ||
if (!endRow) endRow = startRow; | ||
if (endRow < startRow) throw new Error('endRow must bigger than startRow'); | ||
var delLines = this._code.slice(startRow, endRow + 1); | ||
this._code = this._code.splice(startRow, endRow - startRow + 1); | ||
if (this.size === 0) { | ||
this._code = this._code.push(this._emptyLine); | ||
} | ||
return delLines; | ||
} | ||
/** | ||
* @param {Row} row | ||
* @param {string|array} code | ||
* @returns {Doc} | ||
*/ | ||
}, { | ||
key: 'insertLines', | ||
value: function insertLines(row, code) { | ||
var _this2 = this; | ||
if (row > this.size) row = this.size; | ||
code = typeof code === 'string' ? code.split(_constants.ENDED_REG) : code; | ||
code = code.map(function (content) { | ||
return _this2._createLine(content); | ||
}); | ||
this._code = this._code.slice(0, row).concat(code).concat(this._code.slice(row)); | ||
return this; | ||
} | ||
/** | ||
* @param {Row} row - 如果超出size, 则插入到最后一行 | ||
* @param {string} content | ||
* @returns {Doc} | ||
*/ | ||
}, { | ||
key: 'insertLine', | ||
value: function insertLine(row, content) { | ||
if (row > this.size) row = this.size; | ||
this._code = this._code.slice(0, row).push(this._createLine(content)).concat(this._code.slice(row)); | ||
return this; | ||
} | ||
/** | ||
* @param {Row} row | ||
* @param {number} col | ||
* @returns {Doc} | ||
*/ | ||
}, { | ||
key: 'splitLine', | ||
value: function splitLine(row, col) { | ||
var line = this.getLineContent(row); | ||
var preChars = line.slice(0, col); | ||
var afterChars = line.slice(col); | ||
return this.updateLine(row, preChars).insertLine(row + 1, afterChars); | ||
} | ||
/** | ||
* @param {Row} startRow | ||
* @param {Row} endRow | ||
* @return {Doc} | ||
*/ | ||
}, { | ||
key: 'joinLines', | ||
value: function joinLines(startRow, endRow) { | ||
if (!(startRow < endRow) || startRow > this.size - 1 || startRow < 0) return this; | ||
endRow = endRow > this.size - 1 ? this.size - 1 : endRow; | ||
var times = endRow - startRow; | ||
while (times--) { | ||
var line = this.getLineContent(startRow); | ||
var nextLine = this.getLineContent(startRow + 1); | ||
this.updateLine(startRow, line + nextLine).delLine(startRow + 1); | ||
} | ||
return this; | ||
} | ||
/** | ||
* 删除同一行中得字符 | ||
* @param {Row} row | ||
* @param {number} col | ||
* @param {number} len | ||
* @return {Doc} | ||
*/ | ||
}, { | ||
key: 'delChars', | ||
value: function delChars(row, col) { | ||
var len = arguments.length <= 2 || arguments[2] === undefined ? 1 : arguments[2]; | ||
if (row < 0 || col < 0 || row >= this.size) return this; | ||
var line = this.getLineContent(row); | ||
var newLine = line.slice(0, col) + line.slice(col + len); | ||
return this.updateLine(row, newLine); | ||
} | ||
/** | ||
* 删除同一行字符到行尾 | ||
* @param {Row} row | ||
* @param {number} col | ||
* @return {Doc} | ||
*/ | ||
}, { | ||
key: 'delCharsToEnd', | ||
value: function delCharsToEnd(row, col) { | ||
if (row < 0 || col < 0 || row >= this.size) return this; | ||
var line = this.getLineContent(row); | ||
var newLine = line.slice(0, col); | ||
return this.updateLine(row, newLine); | ||
} | ||
/** | ||
* @param {Row} row | ||
* @param {number} col | ||
* @param {string} chars | ||
* @returns {Doc} | ||
*/ | ||
}, { | ||
key: 'insertChars', | ||
value: function insertChars(row, col, chars) { | ||
if (row < 0 || col < 0 || row >= this.size) return this; | ||
var line = this.getLineContent(row); | ||
var newLine = line.slice(0, col) + chars + line.slice(col); | ||
return this.updateLine(row, newLine); | ||
} | ||
/** | ||
* 跨行删除字符 | ||
* @param {Pos} rangeStart - 开始点 | ||
* @param {Pos} rangeEnd - 结束点 | ||
* @return {Doc} | ||
*/ | ||
}, { | ||
key: 'delCharsByRange', | ||
value: function delCharsByRange(rangeStart, rangeEnd) { | ||
var _toNormalSequence = (0, _utils.toNormalSequence)(rangeStart, rangeEnd); | ||
// 交换位置 | ||
var _toNormalSequence2 = _slicedToArray(_toNormalSequence, 2); | ||
rangeStart = _toNormalSequence2[0]; | ||
rangeEnd = _toNormalSequence2[1]; | ||
var startRow = rangeStart.row; | ||
var endRow = rangeEnd.row; | ||
if (endRow >= this.size) { | ||
throw new Error('range overload.'); | ||
} | ||
if (startRow === endRow) { | ||
return this.delChars(startRow, rangeStart.col, rangeEnd.col - rangeStart.col + 1); | ||
} | ||
var endChars = this.getLineContent(endRow).slice(rangeEnd.col + 1); | ||
this.delCharsToEnd(startRow, rangeStart.col).insertChars(startRow, rangeStart.col, endChars); | ||
this.delLines(startRow + 1, endRow); | ||
return this; | ||
} | ||
}, { | ||
key: 'hashCode', | ||
@@ -99,6 +324,8 @@ value: function hashCode() { | ||
}, { | ||
key: 'toJS', | ||
value: function toJS() { | ||
return this._code.toJS(); | ||
} | ||
}, { | ||
key: 'code', | ||
set: function set(newCode) { | ||
this._code = newCode; | ||
}, | ||
get: function get() { | ||
@@ -105,0 +332,0 @@ return this._code; |
@@ -174,3 +174,3 @@ 'use strict'; | ||
if (st.trimNext() !== ':') { | ||
return this.error('object syntax error.', st.pos); | ||
return this.error('object syntax error.', st); | ||
} | ||
@@ -183,3 +183,3 @@ st.style('operator', 'space'); | ||
} | ||
return this.error('object syntax error.', st.pos); | ||
return this.error('object syntax error.', st); | ||
} | ||
@@ -191,3 +191,3 @@ }, { | ||
if (ctx.get('mustEatArrayItem') && (ch === ']' || ch === ',')) { | ||
return this.error('array syntax error.', st.pos); | ||
return this.error('array syntax error.', st); | ||
} | ||
@@ -240,3 +240,3 @@ if (ch === ']') { | ||
} | ||
return this.error('string syntax error.', st.pos); | ||
return this.error('string syntax error.', st); | ||
} | ||
@@ -277,3 +277,3 @@ }, { | ||
if (isNaN(number)) { | ||
return this.error('bad number.', st.pos); | ||
return this.error('bad number.', st); | ||
} | ||
@@ -306,3 +306,3 @@ return number; | ||
} catch (e) { | ||
return this.error('word syntax error.', st.pos); | ||
return this.error('word syntax error.', st); | ||
} | ||
@@ -309,0 +309,0 @@ |
@@ -95,6 +95,2 @@ 'use strict'; | ||
this._row = opts.startRow === undefined ? this._row : opts.startRow; | ||
var delayed = opts.delayed ? this._delayed : function (_fn) { | ||
_fn(); | ||
}; | ||
var size = this._doc.size; | ||
var ended = function ended() { | ||
@@ -105,5 +101,11 @@ _this._parsing = false; | ||
return new Promise(function (res) { | ||
var delayed = opts.delayed ? _this._delayed : function (_fn) { | ||
_fn(); | ||
}; | ||
var size = _this._doc.size; | ||
if (_this._row >= size) { | ||
return res(); | ||
} | ||
// 开始渲染 | ||
_this._parsing = true; | ||
var run = function run() { | ||
@@ -115,3 +117,3 @@ if (_this._keepOnLines === 0) { | ||
_this._keepOnLines && _this._keepOnLines--; | ||
var str = _this._doc.getRowContent(_this._row); | ||
var str = _this._doc.getLineContent(_this._row); | ||
var stream = new _StringStream2['default'](str, { tabSize: _this._tabSize, saveStyle: opts.saveStyle }); | ||
@@ -130,6 +132,6 @@ while (!stream.eol()) { | ||
}; | ||
// 开始渲染 | ||
_this._parsing = true; | ||
delayed(run, opts.delayTime); | ||
})['catch'](function (e) { | ||
// if error, exec the fn too. | ||
fn && fn(e.stream, e.row); | ||
ended(); | ||
@@ -143,10 +145,11 @@ _this.emit('error', e); | ||
* @param {string} msg | ||
* @param {number} col | ||
* @param {StringStream} stream | ||
*/ | ||
}, { | ||
key: 'error', | ||
value: function error(msg, col) { | ||
value: function error(msg, stream) { | ||
var errorMsg = ''; | ||
var lines = undefined, | ||
afterLines = undefined; | ||
var col = stream.pos; | ||
col = col - 1; // backup one col | ||
@@ -160,2 +163,3 @@ col = col < 0 ? 0 : col; | ||
_err.col = col; | ||
_err.stream = stream; | ||
throw _err; | ||
@@ -165,15 +169,16 @@ } | ||
var preRow = row - ERR_LIMIT + 1 < 0 ? 0 : row - ERR_LIMIT + 1; | ||
errorMsg = (0, _utils.emptySpace)(4) + colors.black(this._doc.getRowContent(row).slice(0, col)) + colors.red(errorMsg + '^ ' + msg); | ||
errorMsg = (0, _utils.emptySpace)(4) + colors.black(this._doc.getLineContent(row).slice(0, col)) + colors.red(errorMsg + '^ ' + msg); | ||
lines = this._doc.code.slice(preRow, row + 1).map(function (text, index, arr) { | ||
return row - arr.size + index + 2 + ' | ' + text; | ||
return row - arr.size + index + 1 + ' | ' + text.get('content'); | ||
}); | ||
lines.push(errorMsg); | ||
lines = lines.push(errorMsg); | ||
afterLines = this._doc.code.slice(row + 1, row + 1 + ERR_LIMIT).map(function (text, index) { | ||
return row + index + 2 + ' | ' + text; | ||
return row + index + 1 + ' | ' + text.get('content'); | ||
}); | ||
lines = lines.concat(afterLines); | ||
var err = new Error(colors.bgBlack('\n' + lines.join('\n'))); | ||
var err = new Error(colors.bgBlack('\n' + lines.toJS().join('\n'))); | ||
err.text = msg; | ||
err.row = row; | ||
err.col = col; | ||
err.stream = stream; | ||
throw err; | ||
@@ -279,4 +284,3 @@ } | ||
var startRow = opts.startRow === undefined ? this._row : opts.startRow; | ||
// const preCtx = this._doc.getRow | ||
var preRow = this._doc.getRow(startRow - 1); | ||
var preRow = this._doc.getLine(startRow - 1); | ||
var preCtx = undefined; | ||
@@ -299,4 +303,4 @@ if (preRow && (preCtx = preRow.context)) { | ||
// update context to doc | ||
_this3._doc.code = _this3._doc.updateRow(row, ctx); | ||
return _this3._doc.getRow(row); | ||
_this3._doc.updateLine(row, ctx); | ||
return _this3._doc.getLine(row); | ||
}, opts).then(function () { | ||
@@ -411,2 +415,7 @@ _this3._res = _this3.ctx.toJS(); | ||
} | ||
/** | ||
* @typedef {number} Row | ||
* @returns {Row} | ||
*/ | ||
}, { | ||
@@ -417,2 +426,6 @@ key: 'row', | ||
} | ||
/** | ||
* @returns {Doc} | ||
*/ | ||
}, { | ||
@@ -419,0 +432,0 @@ key: 'doc', |
@@ -26,2 +26,3 @@ 'use strict'; | ||
} | ||
function readStack(str, stack, fn) { | ||
@@ -63,3 +64,15 @@ var pre = 0; | ||
} | ||
function isBigger(p1, p2) { | ||
return p1.row > p2.row || p1.row === p2.row && p1.col > p2.col; | ||
} | ||
/** | ||
* @param {Pos} p1 | ||
* @param {Pos} p2 | ||
* @return {array<Pos>} | ||
*/ | ||
function toNormalSequence(p1, p2) { | ||
return isBigger(p1, p2) ? [p2, p1] : [p1, p2]; | ||
} | ||
module.exports = { | ||
@@ -69,3 +82,4 @@ Delayed: Delayed, | ||
readStack: readStack, | ||
addStyle: addStyle | ||
addStyle: addStyle, | ||
toNormalSequence: toNormalSequence | ||
}; |
{ | ||
"name": "caesar-parser", | ||
"version": "0.2.2", | ||
"version": "0.2.3", | ||
"description": "", | ||
@@ -44,5 +44,7 @@ "main": "lib/index.js", | ||
"precommit-hook": "~3.0.0", | ||
"eslint-plugin-react": "~3.8.0", | ||
"rimraf": "~2.4.2", | ||
"should": "~7.0.4", | ||
"webpack": "~1.12.0" | ||
"webpack": "~1.12.0", | ||
"react": "~0.13.3" | ||
}, | ||
@@ -49,0 +51,0 @@ "engines": { |
218
src/Doc.js
import immutable, {Map, List} from 'immutable' | ||
import {ENDED_REG} from './constants' | ||
import {toNormalSequence} from './utils' | ||
const emptyStack = new List() | ||
let count = 0 | ||
let __count = 0 | ||
/** | ||
* @typedef {object} Pos | ||
* @property {number} row - 行 | ||
* @property {number} col - 列 | ||
*/ | ||
/** | ||
* parser document | ||
*/ | ||
class Doc { | ||
/** | ||
* @param {string|array}code | ||
* @param {string|array} code | ||
*/ | ||
@@ -15,14 +24,43 @@ constructor(code) { | ||
code = typeof code === 'string' ? code.split(ENDED_REG) : code | ||
this._emptyLine = this._createLine('') | ||
code = code.map((content)=> { | ||
return this._createRow({content}) | ||
return this._createLine(content) | ||
}) | ||
this._code = new immutable.List(code) | ||
} | ||
getRow(row) { | ||
/** | ||
* 获取行 | ||
* @param {Row} row | ||
* @returns {Line} | ||
*/ | ||
getLine(row) { | ||
return this._code.get(row) | ||
} | ||
getRowContent(row) { | ||
/** | ||
* @param {Row} row | ||
* @returns {string} | ||
*/ | ||
getLineContent(row) { | ||
return this._code.getIn([row, 'content']) | ||
} | ||
_createRow({content, styleStack, indentStack, context}) { | ||
/** | ||
* @param {string} content | ||
* @param {object} [addition] | ||
* { | ||
* {array} styleStack | ||
* {array} indentStack | ||
* {Context} context | ||
* } | ||
* @returns {Line} | ||
* @private | ||
*/ | ||
_createLine(content, addition = {}) { | ||
const {styleStack, context, indentStack} = addition | ||
/** | ||
* @typedef {Immutable.Map} Line | ||
* @property {string} content - 行 | ||
* @property {number} id - id, 唯一 | ||
* @property {Immutable.List} styleStack - highlight样式 | ||
* @property {Immutable.List} indentStack - 缩进样式 | ||
*/ | ||
const line = new Map({ | ||
@@ -34,3 +72,3 @@ content: content !== undefined ? content : '', | ||
// 没创建的行都会有唯一的标记 | ||
line.id = count ++ | ||
line.id = __count ++ | ||
// context 不保存到Map里以免影响hashCode判断 | ||
@@ -40,19 +78,169 @@ line.context = context | ||
} | ||
updateRow(index, data = {}) { | ||
const oldRow = this.getRow(index) | ||
/** | ||
* @param {Row} row | ||
* @param {string|object} data | ||
* @return {Doc} | ||
*/ | ||
updateLine(row, data = {}) { | ||
const oldRow = this.getLine(row) | ||
data = typeof data === 'string' ? {content: data} : data | ||
const oldContent = oldRow.get('content') | ||
data.content = data.content === undefined ? oldContent : data.content | ||
const newRow = this._createRow(data) | ||
const newContent = data.content === undefined ? oldContent : data.content | ||
const newRow = this._createLine(newContent, data) | ||
// 如果hashCode没变, 则只更新context | ||
if (oldRow.hashCode() === newRow.hashCode()) { | ||
oldRow.context = newRow.context === undefined ? oldRow.context : newRow.context | ||
return this._code | ||
return this | ||
} | ||
return this._code.set(index, newRow) | ||
this._code = this._code.set(row, newRow) | ||
return this | ||
} | ||
/** | ||
* @param {Row} row | ||
* @return {Line|null} | ||
*/ | ||
delLine(row) { | ||
return this.delLines(row, row).get(0) | ||
} | ||
/** | ||
* @param {Row} startRow | ||
* @param {Row} endRow | ||
* @return {List<Line>} delLines | ||
*/ | ||
delLines(startRow, endRow) { | ||
if (!endRow) endRow = startRow | ||
if (endRow < startRow) throw new Error('endRow must bigger than startRow') | ||
const delLines = this._code.slice(startRow, endRow + 1) | ||
this._code = this._code.splice(startRow, endRow - startRow + 1) | ||
if (this.size === 0) { | ||
this._code = this._code.push(this._emptyLine) | ||
} | ||
return delLines | ||
} | ||
/** | ||
* @param {Row} row | ||
* @param {string|array} code | ||
* @returns {Doc} | ||
*/ | ||
insertLines(row, code) { | ||
if (row > this.size) row = this.size | ||
code = typeof code === 'string' ? code.split(ENDED_REG) : code | ||
code = code.map((content)=> { | ||
return this._createLine(content) | ||
}) | ||
this._code = this._code | ||
.slice(0, row) | ||
.concat(code) | ||
.concat(this._code.slice(row)) | ||
return this | ||
} | ||
/** | ||
* @param {Row} row - 如果超出size, 则插入到最后一行 | ||
* @param {string} content | ||
* @returns {Doc} | ||
*/ | ||
insertLine(row, content) { | ||
if (row > this.size) row = this.size | ||
this._code = this._code | ||
.slice(0, row) | ||
.push(this._createLine(content)) | ||
.concat(this._code.slice(row)) | ||
return this | ||
} | ||
/** | ||
* @param {Row} row | ||
* @param {number} col | ||
* @returns {Doc} | ||
*/ | ||
splitLine(row, col) { | ||
const line = this.getLineContent(row) | ||
const preChars = line.slice(0, col) | ||
const afterChars = line.slice(col) | ||
return this | ||
.updateLine(row, preChars) | ||
.insertLine(row + 1, afterChars) | ||
} | ||
/** | ||
* @param {Row} startRow | ||
* @param {Row} endRow | ||
* @return {Doc} | ||
*/ | ||
joinLines(startRow, endRow) { | ||
if (!(startRow < endRow) || startRow > this.size - 1 || startRow < 0) return this | ||
endRow = endRow > this.size - 1 ? this.size - 1 : endRow | ||
let times = endRow - startRow | ||
while (times--) { | ||
const line = this.getLineContent(startRow) | ||
const nextLine = this.getLineContent(startRow + 1) | ||
this | ||
.updateLine(startRow, line + nextLine) | ||
.delLine(startRow + 1) | ||
} | ||
return this | ||
} | ||
/** | ||
* 删除同一行中得字符 | ||
* @param {Row} row | ||
* @param {number} col | ||
* @param {number} len | ||
* @return {Doc} | ||
*/ | ||
delChars(row, col, len = 1) { | ||
if (row < 0 || col < 0 || row >= this.size) return this | ||
const line = this.getLineContent(row) | ||
const newLine = line.slice(0, col) + line.slice(col + len) | ||
return this.updateLine(row, newLine) | ||
} | ||
/** | ||
* 删除同一行字符到行尾 | ||
* @param {Row} row | ||
* @param {number} col | ||
* @return {Doc} | ||
*/ | ||
delCharsToEnd(row, col) { | ||
if (row < 0 || col < 0 || row >= this.size) return this | ||
const line = this.getLineContent(row) | ||
const newLine = line.slice(0, col) | ||
return this.updateLine(row, newLine) | ||
} | ||
/** | ||
* @param {Row} row | ||
* @param {number} col | ||
* @param {string} chars | ||
* @returns {Doc} | ||
*/ | ||
insertChars(row, col, chars) { | ||
if (row < 0 || col < 0 || row >= this.size) return this | ||
const line = this.getLineContent(row) | ||
const newLine = line.slice(0, col) + chars + line.slice(col) | ||
return this.updateLine(row, newLine) | ||
} | ||
/** | ||
* 跨行删除字符 | ||
* @param {Pos} rangeStart - 开始点 | ||
* @param {Pos} rangeEnd - 结束点 | ||
* @return {Doc} | ||
*/ | ||
delCharsByRange(rangeStart, rangeEnd) { | ||
// 交换位置 | ||
[rangeStart, rangeEnd] = toNormalSequence(rangeStart, rangeEnd) | ||
const startRow = rangeStart.row | ||
const endRow = rangeEnd.row | ||
if (endRow >= this.size) { | ||
throw new Error('range overload.') | ||
} | ||
if (startRow === endRow) { | ||
return this.delChars(startRow, rangeStart.col, rangeEnd.col - rangeStart.col + 1) | ||
} | ||
const endChars = this.getLineContent(endRow).slice(rangeEnd.col + 1) | ||
this.delCharsToEnd(startRow, rangeStart.col).insertChars(startRow, rangeStart.col, endChars) | ||
this.delLines(startRow + 1, endRow) | ||
return this | ||
} | ||
hashCode() { | ||
return this._code.hashCode() | ||
} | ||
set code(newCode) { | ||
this._code = newCode | ||
toJS() { | ||
return this._code.toJS() | ||
} | ||
@@ -59,0 +247,0 @@ get code() { |
@@ -134,3 +134,3 @@ import Parser from './Parser' | ||
if (st.trimNext() !== ':') { | ||
return this.error('object syntax error.', st.pos) | ||
return this.error('object syntax error.', st) | ||
} | ||
@@ -143,3 +143,3 @@ st.style('operator', 'space') | ||
} | ||
return this.error('object syntax error.', st.pos) | ||
return this.error('object syntax error.', st) | ||
} | ||
@@ -149,3 +149,3 @@ _array(st, ctx) { | ||
if (ctx.get('mustEatArrayItem') && (ch === ']' || ch === ',')) { | ||
return this.error('array syntax error.', st.pos) | ||
return this.error('array syntax error.', st) | ||
} | ||
@@ -193,3 +193,3 @@ if (ch === ']') { | ||
} | ||
return this.error('string syntax error.', st.pos) | ||
return this.error('string syntax error.', st) | ||
} | ||
@@ -229,3 +229,3 @@ | ||
if (isNaN(number)) { | ||
return this.error('bad number.', st.pos) | ||
return this.error('bad number.', st) | ||
} | ||
@@ -257,3 +257,3 @@ return number | ||
} catch (e) { | ||
return this.error('word syntax error.', st.pos) | ||
return this.error('word syntax error.', st) | ||
} | ||
@@ -260,0 +260,0 @@ |
@@ -49,4 +49,2 @@ import {EventEmitter} from 'events' | ||
this._row = opts.startRow === undefined ? this._row : opts.startRow | ||
const delayed = opts.delayed ? this._delayed : function(_fn) { _fn() } | ||
const size = this._doc.size | ||
const ended = () => { | ||
@@ -57,5 +55,9 @@ this._parsing = false | ||
return new Promise((res)=> { | ||
const delayed = opts.delayed ? this._delayed : function(_fn) { _fn() } | ||
const size = this._doc.size | ||
if (this._row >= size) { | ||
return res() | ||
} | ||
// 开始渲染 | ||
this._parsing = true | ||
const run = ()=> { | ||
@@ -67,3 +69,3 @@ if (this._keepOnLines === 0) { | ||
this._keepOnLines && (this._keepOnLines --) | ||
const str = this._doc.getRowContent(this._row) | ||
const str = this._doc.getLineContent(this._row) | ||
const stream = new StringStream(str, {tabSize: this._tabSize, saveStyle: opts.saveStyle}) | ||
@@ -82,6 +84,6 @@ while (!stream.eol()) { | ||
} | ||
// 开始渲染 | ||
this._parsing = true | ||
delayed(run, opts.delayTime) | ||
}).catch((e) => { | ||
// if error, exec the fn too. | ||
fn && fn(e.stream, e.row) | ||
ended() | ||
@@ -94,7 +96,8 @@ this.emit('error', e) | ||
* @param {string} msg | ||
* @param {number} col | ||
* @param {StringStream} stream | ||
*/ | ||
error(msg, col) { | ||
error(msg, stream) { | ||
let errorMsg = '' | ||
let lines, afterLines | ||
let col = stream.pos | ||
col = col - 1 // backup one col | ||
@@ -108,2 +111,3 @@ col = col < 0 ? 0 : col | ||
err.col = col | ||
err.stream = stream | ||
throw err | ||
@@ -113,11 +117,12 @@ } | ||
const preRow = row - ERR_LIMIT + 1 < 0 ? 0 : row - ERR_LIMIT + 1 | ||
errorMsg = emptySpace(4) + colors.black(this._doc.getRowContent(row).slice(0, col)) + colors.red(errorMsg + '^ ' + msg) | ||
lines = this._doc.code.slice(preRow, row + 1).map((text, index, arr) => (row - arr.size + index + 2) + ' | ' + text ) | ||
lines.push(errorMsg) | ||
afterLines = this._doc.code.slice(row + 1, row + 1 + ERR_LIMIT).map((text, index) => (row + index + 2) + ' | ' + text ) | ||
errorMsg = emptySpace(4) + colors.black(this._doc.getLineContent(row).slice(0, col)) + colors.red(errorMsg + '^ ' + msg) | ||
lines = this._doc.code.slice(preRow, row + 1).map((text, index, arr) => (row - arr.size + index + 1) + ' | ' + text.get('content')) | ||
lines = lines.push(errorMsg) | ||
afterLines = this._doc.code.slice(row + 1, row + 1 + ERR_LIMIT).map((text, index) => (row + index + 1) + ' | ' + text.get('content') ) | ||
lines = lines.concat(afterLines) | ||
const err = new Error(colors.bgBlack('\n' + lines.join('\n'))) | ||
const err = new Error(colors.bgBlack('\n' + lines.toJS().join('\n'))) | ||
err.text = msg | ||
err.row = row | ||
err.col = col | ||
err.stream = stream | ||
throw err | ||
@@ -189,4 +194,3 @@ } | ||
const startRow = opts.startRow === undefined ? this._row : opts.startRow | ||
// const preCtx = this._doc.getRow | ||
const preRow = this._doc.getRow(startRow - 1) | ||
const preRow = this._doc.getLine(startRow - 1) | ||
let preCtx | ||
@@ -209,4 +213,4 @@ if (preRow && (preCtx = preRow.context)) { | ||
// update context to doc | ||
this._doc.code = this._doc.updateRow(row, ctx) | ||
return this._doc.getRow(row) | ||
this._doc.updateLine(row, ctx) | ||
return this._doc.getLine(row) | ||
}, opts).then(()=> { | ||
@@ -284,5 +288,12 @@ this._res = this.ctx.toJS() | ||
} | ||
/** | ||
* @typedef {number} Row | ||
* @returns {Row} | ||
*/ | ||
get row() { | ||
return this._row | ||
} | ||
/** | ||
* @returns {Doc} | ||
*/ | ||
get doc() { | ||
@@ -289,0 +300,0 @@ return this._doc |
@@ -20,2 +20,3 @@ function Delayed(ms = 0) { | ||
} | ||
function readStack(str, stack, fn) { | ||
@@ -57,3 +58,15 @@ let pre = 0 | ||
} | ||
function isBigger(p1, p2) { | ||
return p1.row > p2.row || (p1.row === p2.row && p1.col > p2.col) | ||
} | ||
/** | ||
* @param {Pos} p1 | ||
* @param {Pos} p2 | ||
* @return {array<Pos>} | ||
*/ | ||
function toNormalSequence(p1, p2) { | ||
return isBigger(p1, p2) ? [p2, p1] : [p1, p2] | ||
} | ||
module.exports = { | ||
@@ -64,2 +77,3 @@ Delayed, | ||
addStyle, | ||
toNormalSequence, | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
75057
2472
15