热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

文本替换后匹配子串的光标位置

如何解决《文本替换后匹配子串的光标位置》经验,请问有什么解决方案?

TL; DR

我有替换文本,字符串和光标位置(数字)的函数,我需要获取使用replace函数创建的新字符串的更正位置(数字),如果字符串更改的长度:

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');
});

然后当命令行获取新字符串时光标位置错误.

我试着解决这个问题,但它没有按预期工作,终端的内部看起来像这样,

当我改变时,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  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  1) {
            return diff;
        }
    }
    return 0;
}

...

} else if (len  command_len) {
    formatted_position += find_diff();
}

但是我觉得更糟糕的是因为当光标位于替换单词之前或之中时它会发现差异,只有当光标位于替换单词的中间时才会找到diff.

您可以在此codepen中看到我尝试的结果https://codepen.io/jcubic/pen/qPVMPg?editors=0110(允许输入表情符号和foo bar baz替换为text_$1)

更新:

我用这段代码做了一些工作:

    // ---------------------------------------------------------------------
    // :: 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  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  len) {
                formatted_position = len;
            } else if (formatted_position <0) {
                formatted_position = 0;
            }
        }
        return formatted_position;
    }

当您将表情符号键入为第一个字符并且光标位于以下位置时,它不适用于一个案例:smile:word.更换后如何修复get_formatted_position函数以获得正确的固定位置?

更新:我问了不同的简单问题并使用了接受正则表达式和字符串的trackingReplace函数得到了解决方案,所以我更改了格式化程序的API以接受带有正则表达式的字符串和字符串沿着函数更正后的子字符串位置


推荐阅读
author-avatar
t53457078
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有