TL; DRVị trí con trỏ phù hợp cho chuỗi con sau văn bản thay thế
Tôi có chức năng thay thế văn bản, chuỗi và vị trí con trỏ (số) và tôi cần sửa vị trí (số) cho chuỗi mới tạo ra với chức năng thay thế nếu chiều dài nếu sự thay đổi chuỗi:
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
vấn đề là tôi có thể sử dụng chuỗi trên văn bản gốc nhưng sau đó thay thế sẽ không phù hợp với toàn bộ từ vì thế nó cần phải được thực hiện cho toàn bộ văn bản nhưng sau đó chuỗi con sẽ không khớp với phần thay thế.
Tôi cũng ổn với giải pháp con trỏ luôn ở cuối từ khi con trỏ ban đầu ở giữa từ được thay thế.
và bây giờ thực hiện của tôi, trong jQuery ga tôi có một loạt các trình định dạng chức năng trong:
$.terminal.defaults.formatters
họ chấp nhận một chuỗi và nó sẽ trả về chuỗi mới cho nó hoạt động tốt, ngoại trừ trường hợp này:
khi Tôi có định dạng độ dài thay đổi đó nếu phá vỡ dòng lệnh, ví dụ: trình định dạng này:
$.terminal.defaults.formatters.push(function(string) {
return string.replace(/:smile:/g, 'a')
.replace(/(foo|bar|baz)/g, 'text_$1');
});
thì vị trí con trỏ sai khi lệnh li ne nhận được chuỗi mới.
Tôi đã cố gắng khắc phục điều này nhưng nó không làm việc như mong đợi, nội bộ của giao diện thiết bị đầu cuối như thế này,
khi tôi thay đổi position
Tôi đóng thùng một biến khác formatted_position
đó là sử dụng trong dòng lệnh để hiển thị con trỏ. để có được giá trị mà tôi sử dụng này:
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 và $ .terminal.length là hàm helper được định dạng thiết bị đầu cuối nhận biết (văn bản trông giống như [[b;#fff;]hello]
này) nếu bạn sẽ viết giải pháp bạn có thể sử dụng văn bản bình thường và sử dụng các phương thức chuỗi.
vấn đề là khi tôi di chuyển con trỏ ở giữa các từ có nghĩa là thay đổi
nó loại công việc khi văn bản dài hơn, nhưng đối với chuỗi ngắn nhảy con trỏ sang bên phải khi văn bản là trong giữa từ đã được thay thế.
Tôi đã cố gắng khắc phục điều này cũng sử dụng mã này:
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();
}
nhưng điều này tôi nghĩ rằng làm cho nó thậm chí tệ hơn bởi vì nó tìm diff khi con trỏ là trước hoặc ở giữa chữ thay thế và nó nên chỉ tìm thấy khác khi con trỏ ở giữa từ được thay thế.
Bạn có thể xem kết quả của những nỗ lực của tôi trong codepen https://codepen.io/jcubic/pen/qPVMPg?editors=0110 này (cho phép gõ biểu tượng cảm xúc và foo bar baz được thay thế bởi text_$1
)
CẬP NHẬT:
tôi đã làm cho nó loại làm việc với mã này:
// ---------------------------------------------------------------------
// :: 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;
}
nó không hoạt động cho một trường hợp khi bạn nhập biểu tượng cảm xúc làm ký tự đầu tiên và con trỏ ở giữa: smile: word. Cách sửa hàm get_formatted_position để có vị trí cố định chính xác sau khi thay thế?
CẬP NHẬT: Tôi đã hỏi câu hỏi khác nhau và đơn giản và có những giải pháp sử dụng chức năng trackingReplace chấp nhận regex và chuỗi, vì vậy tôi đã thay đổi API cho trình định dạng để chấp nhận mảng với regex và chuỗi dọc theo chức năng Correct substring position after replacement
Bạn có chắc chắn, di chuyển con trỏ vào từ được thay thế không? Đối với tôi nó có vẻ khá khó hiểu. Tôi sẽ nhìn vào Word, hoặc tài liệu google nếu họ không di chuyển nó ở đầu hoặc cuối. – Akxe
@Akxe đó là trường hợp hoàn toàn khác so với từ hoặc tài liệu google, bởi vì văn bản được thay thế trong khi bạn nhập không khi bạn thay thế văn bản như trong chức năng tìm kiếm/thay thế. Và nó trông rất lạ khi bạn không thay đổi vị trí bởi vì bạn có thể kết thúc phần cuối của văn bản có độ dài là 10 và văn bản thay thế là 3 và bạn nhận được vị trí của 10 nó phải là 3. – jcubic
Ý tôi là, nếu bạn thay thế từ con trỏ của bạn hiện đang ở bên trong, sau đó có thể tốt hơn là đặt con trỏ ở phía trước hoặc sau từ mới được thay thế. Và Word chắc chắn có tùy chọn để thay thế. – Akxe