Non penso che dovresti avere le informazioni di evidenziazione della sintassi direttamente nel tuo buffer di testo. Invece, vorrei aggiungere ulteriori strutture di dati per il codice di visualizzazione.
Ecco perché:
Una volta fornite funzionalità come selezioni, ecc. probabilmente avrai bisogno di un concetto di ancoraggio (un puntatore fisso a una posizione specifica nel buffer, anche quando i caratteri vengono inseriti o eliminati prima di quella posizione - vedi sotto per l'idea di implementazione) . Se hai a che fare con testi più lunghi, potresti anche aver bisogno di questi ancore per fornire un indice veloce nel tuo buffer per l'inizio della linea (dato che stai utilizzando un buffer di spazio, hai bisogno di un modo per tradurre i numeri di riga in posizioni di buffer).
Quello che sto ottenendo è che sono necessarie diverse strutture di dati di supporto oltre al buffer di testo effettivo per fornire comandi rapidi di editor standard e visualizzare il buffer attualmente visibile. Nonostante la tua decisione di utilizzare un buffer gap, gli editor sono basati su linee e dovrai sostenerlo in qualche modo. Quindi, perché non scrivere un evidenziatore di sintassi basato sulla linea che prenderà il buffer di testo, un'ancora in esso (che dovrebbe idealmente essere l'inizio di una riga) e uno stato di evidenziazione e produrrà una lista di ("frammento di testo", "informazioni di stile" ") si accoppia alla fine della linea, che il tuo codice di visualizzazione userà per visualizzare effettivamente questa linea? Se non è abbastanza veloce da fare al volo, è possibile creare una cache di questi elenchi indicizzati dal numero di riga. Potresti farlo anche per l'intero file in una volta, ma sospetto che le prestazioni ne risentiranno se lo fai ogni volta che ti muovi nel tuo file.
Avrai bisogno dello stato di evidenziatore come input a causa di token multi-linea come lunghi commenti o stringhe. Poiché di solito un editor visualizza un file dall'inizio quando viene aperto per la prima volta, puoi iniziare con uno stato "tutto chiaro", chiamare il codice dell'evidenziatore per sputare le informazioni di evidenziazione della prima riga e mantenere lo stato di evidenziatore alla fine di la linea (ad esempio "attualmente in un commento su più righe" o "tutto chiaro") come stato dell'evidenziatore all'inizio della riga successiva.
Quindi, in sostanza, suggerirei di implementare ancore e quindi mantenere un indice per tradurre rapidamente i numeri di riga in ancore di buffer di testo. Quindi aggiungerei questo indice per fornire non solo ancore nel buffer di testo ma anche una cache di output dell'evidenziatore della sintassi per quella riga e lo stato di evidenziatore all'inizio di questa riga. Quindi se l'utente sta modificando una linea, non è necessario riavviare l'evidenziatore nella parte superiore del buffer; è sufficiente riavviare l'evidenziazione all'inizio della riga; e se sei intelligente, puoi anche evitare di dover evidenziare l'intero resto del buffer (penso che tu smetta di evidenziare non appena raggiungi la parte inferiore dell'area visibile o una linea con lo stesso stato dell'evidenziatore) in realtà, ma contrassegna i seguenti stati evidenziatore come "probabilmente obsoleti" se lo stato di evidenziatore non corrisponde a quello memorizzato nella cache per la riga successiva.
Penso che tu possa farla franca solo mettendo in evidenza sezioni molto piccole del tuo buffer in questo modo, di solito solo una singola riga, ad eccezione dei comandi di editor come "vai alla fine del file", nel qual caso dovrai syntax: evidenzia l'intero buffer per determinare lo stato in cui si trova l'evidenziatore alla fine del file.
Modifica: come implementare le ancore
Per implementare ancore, puoi utilizzare eventi e ascoltatori. Ogni volta che il buffer riceve un comando per inserire o eliminare del testo, notifica a tutti gli ascoltatori che questi eventi stanno per accadere. Gli ancoraggi quindi si iscrivono a questi eventi come ascoltatori e si aggiornano in base al tipo di evento. Ad esempio, se sono stati inseriti tre caratteri prima della posizione di ancoraggio, è necessario aggiungere 3 alla posizione di ancoraggio; se i caratteri sono inseriti dopo la posizione di ancoraggio, non è necessaria alcuna azione, ecc. Quindi, in pratica, un ancoraggio è un oggetto che tiene traccia di un offset del buffer e si iscrive per modificare gli eventi dal buffer gap.