TL; DR子字符串匹配光標位置的文本替換後
我有函數替換文本,字符串和光標的位置(數字),我需要得到修正後的位置(數字)的新字符串,它是與替換功能創建如果長度字符串是否變化:
input and cursor position: foo ba|r text
replacement: foo -> baz_text, bar -> quux_text
result: baz_text qu|ux_text text
input and cursor position: foo bar| text
replacement: foo -> baz_text, bar -> quux_text
result: baz_text quux_text| text
input and cursor position: foo bar| text
replacement: foo -> f, bar -> b
result: f b| text
input and cursor position: foo b|ar text
replacement: foo -> f, bar -> b
result: f b| text
的問題是,我可以使用原來的文本串但隨後的更換不會全字匹配,因此需要對整個文本,但隨後做子串將不匹配替換。
我對解決方案也很好,光標始終在單詞的末尾,原始光標位於被替換的單詞的中間。
,現在我的實現,在jQuery的終端我的格式化功能於一身的數組:
$.terminal.defaults.formatters
他們接受一個字符串,它應該返回新的字符串,它做工精細,除了這種情況:
時我有格式化工具改變長度,如果打破了命令行,比如這個格式:
$.terminal.defaults.formatters.push(function(string) {
return string.replace(/:smile:/g, 'a')
.replace(/(foo|bar|baz)/g, 'text_$1');
});
然後將光標定位錯了,當李命令ne得到新的字符串。
我已經嘗試解決此問題,但如預期,內部終端這個樣子的吧不工作,
當我改變position
我裝箱另一個變量
formatted_position
這是在命令行中使用到
顯示光標。獲得該值我使用這個:
formatted_position = position;
var string = formatting(command);
var len = $.terminal.length(string);
var command_len = $.terminal.length(command);
if (len !== command_len) {
var orig_sub = $.terminal.substring(command, 0, position);
var orig_len = $.terminal.length(orig_sub);
var formatted = formatting(orig_sub);
var formatted_len = $.terminal.length(formatted);
if (orig_len > formatted_len) {
// if formatting make substring - (text before cursor)
// shorter then subtract the difference
formatted_position -= orig_len - formatted_len;
} else if (orig_len < formatted_len) {
// if the formatted string is longer add difference
formatted_position += formatted_len - orig_len;
}
}
if (formatted_position > len) {
formatted_position = len;
} else if (formatted_position < 0) {
formatted_position = 0;
}
$ .terminal.substring和$ .terminal.length是那些終端格式化知道(文字看起來像這樣[[b;#fff;]hello]
)的輔助功能,如果你會寫解決方案,您可以使用普通文本和使用字符串方法。
的問題是,當我移動光標在改變
這方面的工作時,文字越長,詞的中間,但對於較短的字符串光標跳到右邊時,文本是在被取代的單詞的中間。
我已經嘗試解決這個使用此代碼,以及:
function find_diff(callback) {
var start = position === 0 ? 0 : position - 1;
for (var i = start; i < command_len; ++i) {
var substr = $.terminal.substring(command, 0, i);
var next_substr = $.terminal.substring(command, 0, i + 1);
var formatted = formatting(next_substr);
var substr_len = $.terminal.length(substr);
var formatted_len = $.terminal.length(formatted);
var diff = Math.abs(substr_len - formatted_len);
if (diff > 1) {
return diff;
}
}
return 0;
}
...
} else if (len < command_len) {
formatted_position -= find_diff();
} else if (len > command_len) {
formatted_position += find_diff();
}
但我認爲讓事情變得更糟,原因是其找到差異時光標之前或更換字的中間,它應該僅當光標位於替換字詞的中間才能找到diff。
你可以看到我的努力的結果,在這個codepen https://codepen.io/jcubic/pen/qPVMPg?editors=0110(即允許輸入表情符號和Foo酒吧巴茲得到由text_$1
代替)
UPDATE:
我讓它有種與此代碼的工作:微笑:字
// ---------------------------------------------------------------------
// :: functions used to calculate position of cursor when formatting
// :: change length of output text like with emoji demo
// ---------------------------------------------------------------------
function split(formatted, normal) {
function longer(str) {
return found && length(str) > length(found) || !found;
}
var formatted_len = $.terminal.length(formatted);
var normal_len = $.terminal.length(normal);
var found;
for (var i = normal_len; i > 1; i--) {
var test_normal = $.terminal.substring(normal, 0, i);
var formatted_normal = formatting(test_normal);
for (var j = formatted_len; j > 1; j--) {
var test_formatted = $.terminal.substring(formatted, 0, j);
if (test_formatted === formatted_normal &&
longer(test_normal)) {
found = test_normal;
}
}
}
return found || '';
}
// ---------------------------------------------------------------------
// :: return index after next word that got replaced by formatting
// :: and change length of text
// ---------------------------------------------------------------------
function index_after_formatting(position) {
var start = position === 0 ? 0 : position - 1;
var command_len = $.terminal.length(command);
for (var i = start; i < command_len; ++i) {
var substr = $.terminal.substring(command, 0, i);
var next_substr = $.terminal.substring(command, 0, i + 1);
var formatted_substr = formatting(substr);
var formatted_next = formatting(next_substr);
var substr_len = length(formatted_substr);
var next_len = length(formatted_next);
var test_diff = Math.abs(next_len - substr_len);
if (test_diff > 1) {
return i;
}
}
}
// ---------------------------------------------------------------------
// :: main function that return corrected cursor position on display
// :: if cursor is in the middle of the word that is shorter the before
// :: applying formatting then the corrected position is after the word
// :: so it stay in place when you move real cursor in the middle
// :: of the word
// ---------------------------------------------------------------------
function get_formatted_position(position) {
var formatted_position = position;
var string = formatting(command);
var len = $.terminal.length(string);
var command_len = $.terminal.length(command);
if (len !== command_len) {
var orig_sub = $.terminal.substring(command, 0, position);
var orig_len = $.terminal.length(orig_sub);
var sub = formatting(orig_sub);
var sub_len = $.terminal.length(sub);
var diff = Math.abs(orig_len - sub_len);
if (false && orig_len > sub_len) {
formatted_position -= diff;
} else if (false && orig_len < sub_len) {
formatted_position += diff;
} else {
var index = index_after_formatting(position);
var to_end = $.terminal.substring(command, 0, index + 1);
//formatted_position -= length(to_end) - orig_len;
formatted_position -= orig_len - sub_len;
if (orig_sub && orig_sub !== to_end) {
var formatted_to_end = formatting(to_end);
var common = split(formatted_to_end, orig_sub);
var re = new RegExp('^' + $.terminal.escape_regex(common));
var to_end_rest = to_end.replace(re, '');
var to_end_rest_len = length(formatting(to_end_rest));
if (common orig_sub !== common) {
var commnon_len = length(formatting(common));
formatted_position = commnon_len + to_end_rest_len;
}
}
}
if (formatted_position > len) {
formatted_position = len;
} else if (formatted_position < 0) {
formatted_position = 0;
}
}
return formatted_position;
}
當你作爲第一個字符表情符號輸入和光標在中間也沒有爲一個案件工作。如何解決get_formatted_position函數在替換後具有正確的固定位置?
更新:我問不同的,簡單的問題,並使用正則表達式接受和字符串trackingReplace功能得到了解決,所以我改變了API,用於格式化接受與正則表達式和字符串一同功能陣列Correct substring position after replacement
你確定,將光標移動到被替換的單詞是正確的嗎?對我來說,這似乎很混亂。如果他們不在開頭或結尾移動它,我會查看Word或Google文檔。 – Akxe
@Akxe它是完全不同的情況比單詞或谷歌文檔,因爲文本被替換時,而不是當你做文字替換時搜索/替換功能。當你不改變位置時,它看起來很奇怪,因爲你可以結束長度爲10的文本的末尾,被替換的文本是3,並且你得到的位置是10,它應該是3. – jcubic
我的意思是,如果你替換光標當前所在的單詞,然後將光標放在前面或在新的替換單詞之後可能會更好。而Word肯定有替代選項。 – Akxe