自动括号插入算法

时间:2019-04-13 13:50:32

标签: c++ algorithm qt text-editor curly-braces

有关更多信息,请参见this issue on GitHub

我想编写一个算法,当用户在大括号后按下Enter键时调用该算法。预期的行为在下面详细说明。


1。。假设我们有一个空文档。如果我们键入一个大括号并按Enter,则预期的行为如下:

Enter image description here

这可以描述为以下简单算法:

  1. 如果在大括号后面按下Enter键,则将光标移到下一行,并在大括号的缩进位置之外再缩进一个级别。

  2. 如果未对开括号进行配对,请在下一行以与开括号相同的缩进高度插入一个闭括号。否则,如果已经配对,则在1.之后不执行任何操作。

换句话说,我们不希望的是如果在已经配对的开头括号之后按Enter键,则要插入另一个结尾括号。相反,我们只是想保持缩进一致:

Enter image description here


2。。现在假设我们在第2行的光标处键入另一个左括号,然后按Enter。我们期望按照上述相同的算法生成一对新的配对:

Enter image description here


3。并且,如果我们转到第1行,请按Enter键几次以将大括号向下压,然后尝试在顶部重新创建一个新块,我们也希望将其配对:

Enter image description here

问题

我无法实现此行为。我正在使用Qt在C ++中开发文本编辑器,但是您不必担心框架的细节。它将是一个实用函数,它将使用给定的名为context的字符串和相关的右大括号的索引,并确定是否应插入右大括号。

我的current implementation满足方案#1和#2,但不满足方案#3。它不满足#3的原因是因为我正在为开括号使用一个队列。

我也尝试过使用一个大括号作为开括号。有趣的是,这最终满足了#1和#3,但不满足#2。

问题

如何根据上述预期行为编写一种算法来确定给定的括号是否已经有匹配对?请注意,我已经在站点上对此进行了研究,并且确实知道如何确定给定的打开括号是否具有匹配的关闭括号。但是,我当前的算法(上面链接)无法按预期工作(失败的地方请参见上面的说明)。

说明:您不必担心整个“缩进”。这已得到照顾并按预期工作。无法正常工作的是确定特定括号是否需要匹配对。

1 个答案:

答案 0 :(得分:1)

要确定是否有一个大括号,这不是一个复杂的问题,缩进将是困难的。如果在ope大括号后有 any 个不匹配的右大括号,则您有一个匹配项。关键在于括号是否在您的开放括号之后。您可以通过以下方式确定这一点:

  1. 存储所有不匹配的右括号的位置;如果您跟随光标,则无需插入右括号
  2. 动态评估光标之前的不匹配括号的数量(不计算不匹配的闭合次数)与光标之后的不匹配括号的数量;如果光标后有多余的右括号,则无需插入右括号

如果您要使用数字 2 ,我将this answer扩展为您需要用来计算括号前后的括号:

bool foo(const string& context, const size_t pos) {
    const auto it = next(cbegin(context), pos);
    const auto before = accumulate(cbegin(context), it, 0, [](const auto output, const auto input) {
        if(input == '{') {
            return output + 1;
        }
        else if(input == '}' && output > 0) {
            return output - 1;
        }
        else {
            return output;
        }
    });
    const auto after = accumulate(it, cend(context), 0, [](const auto output, const auto input) {
        if(input == '{') {
            return output + 1;
        }
        else if(input == '}') {
            return output - 1;
        }
        else {
            return output;
        }
    });

    return before + after >= 0;
}

可以使用有问题的文本(不包括插入的大括号)以及要插入的大括号在字符串中的位置进行调用。给定您的文本包含在const string bar中,并且光标位置位于const size_t baz上,您可以像下面这样调用此函数:foo(bar, baz)如果返回true,则需要添加一个右括号。

Live Example