O que é uma estrutura de dados eficiente para destacar a sintaxe em editores de texto?

5

Estou criando um editor de texto muito pequeno em C ++ com a biblioteca ncurses. Até agora, funciona muito bem. Implementei a estrutura de dados Gap Buffer para tornar a edição mais eficiente do que um buffer baseado em linha. Eu considerei a estrutura de dados do Ropes, mas pareceu muito complexo para isso.

No entanto, estou tentando implementar o realce de sintaxe e não consigo pensar em uma maneira decente de fazer isso. Devo destacar o arquivo inteiro ou apenas a visualização atual (sem destacar as partes não visíveis do arquivo)?

Devo ceder e usar esperanças, armazenando os micro buffers com dados de estilo (negrito, cor, etc)?

    
por vinnylinux 19.08.2015 / 16:10
fonte

1 resposta

8

Eu não acho que você deveria ter informações de realce de sintaxe diretamente no seu buffer de texto. Em vez disso, adicionaria estruturas de dados adicionais para o código de exibição.

Veja por que:

Uma vez que você esteja fornecendo funcionalidades como seleções, etc, provavelmente precisará de um conceito de âncora (um ponteiro fixo para um local específico no buffer, mesmo quando caracteres são inseridos ou excluídos antes desse local - veja abaixo a ideia de implementação) . Se você está lidando com textos mais longos, você também pode precisar dessas âncoras para fornecer um índice rápido em seu buffer para começos de linha (já que você está usando um buffer de gap, você precisa de alguma maneira de traduzir números de linha em posições de buffer).

O que eu estou recebendo é que você precisa de várias estruturas de dados de suporte, além do buffer de texto real, a fim de fornecer comandos editoriais rápidos e exibir o buffer atualmente visível. Apesar de sua decisão de usar um buffer de intervalo, os editores são baseados em linhas e você precisará dar suporte a isso de alguma forma. Então, por que não escrever um marcador de sintaxe baseado em linhas que levará o buffer de texto, uma âncora (que deve idealmente ser o começo de uma linha) e um estado de realce e saída de uma lista de "fragmento de texto". ") pares até o final da linha, que seu código de exibição irá usar para realmente exibir essa linha? Se não for rápido o suficiente para fazer em tempo real, você pode criar um cache dessas listas indexadas pelo número da linha. Você poderia fazer isso para o arquivo inteiro de uma só vez, mas eu suspeito que o desempenho vai sofrer se você fizer isso toda vez que você se mover no seu arquivo.

Você precisará do estado do marcador como entrada por causa de tokens de várias linhas, como comentários longos ou strings. Como normalmente um editor exibe um arquivo desde o início, quando é aberto pela primeira vez, você pode começar com um estado "todo limpo", chamar o código do marcador para citar as informações de realce da primeira linha e manter o estado do marcador no final de a linha (por exemplo, "atualmente em um comentário de várias linhas" ou "todo limpo") como o estado do marcador no início da próxima linha.

Então, basicamente, sugiro implementar âncoras e manter um índice para converter rapidamente os números de linha em âncoras de buffer de texto. Então, eu aumentaria esse índice para fornecer não apenas âncoras no buffer de texto, mas também um cache de saída de marcador de sintaxe para esse estado de linha e marcador no início desta linha. Portanto, se o usuário estiver editando uma linha, você não precisará reiniciar o marca-texto no topo do buffer; você simplesmente reinicia o realce no começo da linha; e se você for esperto, também pode evitar ter que destacar todo o restante do buffer (estou pensando em deixar de destacar assim que você chegar na parte inferior da área visível ou em uma linha com o mesmo estado em que o marcador está na verdade, mas sinalize os seguintes estados do marcador como "possivelmente desatualizados" se o estado do marcador não corresponder ao estado armazenado para a próxima linha.

Eu acho que você pode se destacar apenas com seções muito pequenas de seu buffer desta maneira, geralmente apenas uma única linha, exceto para comandos do editor como "pular para o final do arquivo", caso em que você precisará sintaxe - destaque o buffer inteiro para determinar o estado em que o marcador deveria estar no final do arquivo.

Edit: Como implementar âncoras

Para implementar âncoras, você pode usar eventos e ouvintes. Sempre que o buffer recebe um comando para inserir ou excluir texto, ele notifica todos os ouvintes que esses eventos estão prestes a acontecer. As âncoras então se inscrevem nesses eventos como ouvintes e se atualizam com base no tipo de evento. Por exemplo, se três caracteres forem inseridos antes da posição de âncora, você precisará adicionar 3 à posição de âncora; se os caracteres forem inseridos após a posição da âncora, nenhuma ação é necessária, etc. Então, basicamente, uma âncora é um objeto que mantém o controle de um deslocamento de buffer e se inscreve para alterar eventos do buffer de espaço. / p>     

por 19.08.2015 / 21:48
fonte