Skip to content
This repository has been archived by the owner on Apr 1, 2020. It is now read-only.

[WIP] Feature/token color trie #2621

Open
wants to merge 38 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
5502650
initial effort to get syntax highlighting to reapply on colorscheme r…
akinsho Sep 10, 2018
b47b665
remove lint check for whitespace inside template literals
akinsho Sep 10, 2018
307caa3
neaten reducer reset tidy up comment in bufferhighlight
akinsho Sep 11, 2018
9176536
Refactor token colors to pass token scopes as an array of strings
akinsho Sep 16, 2018
e86a79f
fix imports in token colors
akinsho Sep 16, 2018
8ac5668
pass in only visible tokens to the neovim token synchronizer
akinsho Sep 16, 2018
693cb6b
fix lint errors
akinsho Sep 16, 2018
64998eb
fix another lint error
akinsho Sep 16, 2018
5543d5d
revert token destructuring in reconciler
akinsho Sep 16, 2018
5a7939a
notify redraw when tokencolors change in neovim editor
akinsho Sep 18, 2018
02df5bb
update redux
akinsho Sep 18, 2018
759df55
[wip] get token subset in synchronizeTokenColors
akinsho Sep 19, 2018
30eda55
make cache access more readable
akinsho Sep 27, 2018
83eccd8
remove subset functionality from token synchronizer
akinsho Oct 4, 2018
4873456
convert highlight cache to map so it can be cleared and reused easily
akinsho Oct 7, 2018
d9379fe
do not split tokens on space char as this changes the way tokens are …
akinsho Oct 7, 2018
be57820
revert package json and yarn lock
akinsho Oct 7, 2018
d261b29
move private fields to avoid lint errors
akinsho Oct 7, 2018
5825010
add onColorsChanged to neovim instance mock
akinsho Oct 7, 2018
c0c33f7
fix comments for token formatter function in token colors
akinsho Oct 7, 2018
7a83fb5
create a trie structure for adding token colors
akinsho Sep 16, 2018
4a43ca6
flesh out trie functionality and allow get function for trie
akinsho Sep 16, 2018
f248820
pass in only visible tokens to the neovim token synchronizer
akinsho Sep 16, 2018
b6daa27
query token colors tree for token to use in tokenScorer
akinsho Oct 7, 2018
53ffcfd
add removal and update functionality to Trie
akinsho Oct 7, 2018
7d8281c
make root _ variable to express private-ness
akinsho Oct 7, 2018
0446148
move match functionality out of token scorer into Trie
akinsho Oct 7, 2018
534103b
remove infuriating ordered imports rule
akinsho Oct 7, 2018
47dda64
add token tree to mock Token Colors
akinsho Oct 8, 2018
0dd54b1
fix token scorer tests
akinsho Oct 8, 2018
914d131
correctly update parent scopes for tokens
akinsho Oct 10, 2018
b1f318f
factor parent scopes into token scoring
akinsho Oct 10, 2018
6bdf316
add compare method for parent scopes to the token trie
akinsho Oct 11, 2018
f5f26fe
move the check of the parent scopes to the internals of the token trie
akinsho Oct 11, 2018
bead38c
add reminder comment to eventually remove the token colors array
akinsho Oct 11, 2018
31c8c86
remove third argument from token ranker function
akinsho Oct 11, 2018
8cc0ae4
allow matches against top level tokens
akinsho Oct 11, 2018
28b3539
allow tokens to be selected based on priority
akinsho Oct 11, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions browser/src/Editor/BufferHighlights.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,13 @@ export interface IBufferHighlightsUpdater {
clearHighlightsForLine(line: number): void
}

// Helper class to efficiently update
// buffer highlights in a batch.
/**
* Helper class to efficiently update
* buffer highlights in a batch
*
* @name BufferHighlightsUpdater
* @class
*/
export class BufferHighlightsUpdater implements IBufferHighlightsUpdater {
private _calls: any[] = []

Expand Down
18 changes: 8 additions & 10 deletions browser/src/Editor/NeovimEditor/NeovimEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -315,19 +315,15 @@ export class NeovimEditor extends Editor implements Oni.Editor {
this._actions.setColors(updatedColors)
}

this._colors.onColorsChanged.subscribe(() => onColorsChanged())
this._colors.onColorsChanged.subscribe(onColorsChanged)
onColorsChanged()

const onTokenColorschanged = () => {
if (this._neovimInstance.isInitialized) {
this._neovimInstance.tokenColorSynchronizer.synchronizeTokenColors(
this._tokenColors.tokenColors,
)
}
}

this.trackDisposable(
this._tokenColors.onTokenColorsChanged.subscribe(() => onTokenColorschanged()),
this._tokenColors.onTokenColorsChanged.subscribe(() => {
if (this._neovimInstance.isInitialized) {
this._syntaxHighlighter.notifyColorschemeRedraw(`${this.activeBuffer.id}`)
}
}),
)

// Overlays
Expand Down Expand Up @@ -1292,6 +1288,8 @@ export class NeovimEditor extends Editor implements Oni.Editor {

private async _onColorsChanged(): Promise<void> {
const newColorScheme = await this._neovimInstance.eval<string>("g:colors_name")
const { bufferNumber } = await this._neovimInstance.getContext()
this._syntaxHighlighter.notifyColorschemeRedraw(`${bufferNumber}`)

// In error cases, the neovim API layer returns an array
if (typeof newColorScheme !== "string") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ISyntaxHighlightTokenInfo } from "./SyntaxHighlightingStore"
export interface ISyntaxHighlighter extends IDisposable {
notifyBufferUpdate(evt: Oni.EditorBufferChangedEventArgs): Promise<void>
notifyViewportChanged(bufferId: string, topLineInView: number, bottomLineInView: number): void
notifyColorschemeRedraw(id: string): void

getHighlightTokenAt(bufferId: string, position: types.Position): ISyntaxHighlightTokenInfo
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
* Handles enhanced syntax highlighting
*/

import { Buffer, Editor } from "oni-api"
import * as Log from "oni-core-logging"

import { TokenColor, TokenColors } from "./../TokenColors"

import { NeovimEditor } from "./../../Editor/NeovimEditor"
import { prettyPrint } from "./../../Utility"

import { HighlightInfo } from "./Definitions"
import {
Expand All @@ -18,21 +18,37 @@ import {
} from "./SyntaxHighlightingStore"
import { TokenScorer } from "./TokenScorer"

import { IBufferHighlightsUpdater } from "../../Editor/BufferHighlights"
import * as Selectors from "./SyntaxHighlightSelectors"

// SyntaxHighlightReconciler
//
// Essentially a renderer / reconciler, that will push
// highlight calls to the active buffer based on the active
// window and viewport
interface IBufferWithSyntaxHighlighter extends Buffer {
updateHighlights?: (
tokenColors: TokenColor[],
highlightCallback: (args: IBufferHighlightsUpdater) => void,
) => void
}

export interface IEditorWithSyntaxHighlighter extends Editor {
activeBuffer: IBufferWithSyntaxHighlighter
}

/**
* SyntaxHighlightReconciler
*
* Essentially a renderer / reconciler, that will push
* highlight calls to the active buffer based on the active
* window and viewport
* @name SyntaxHighlightReconciler
* @class
*/
export class SyntaxHighlightReconciler {
private _previousState: { [line: number]: ISyntaxHighlightLineInfo } = {}
private _tokenScorer = new TokenScorer()

constructor(private _editor: NeovimEditor, private _tokenColors: TokenColors) {}
constructor(private _editor: IEditorWithSyntaxHighlighter, private _tokenColors: TokenColors) {}

public update(state: ISyntaxHighlightState) {
const activeBuffer: any = this._editor.activeBuffer
const { activeBuffer } = this._editor

if (!activeBuffer) {
return
Expand Down Expand Up @@ -77,6 +93,15 @@ export class SyntaxHighlightReconciler {
}
})

// Get only the token colors that apply to the visible section of the buffer
const visibleTokens = tokens.reduce((accumulator, { highlights }) => {
if (highlights) {
const tokenColors = highlights.map(({ tokenColor }) => tokenColor)
accumulator.push(...tokenColors)
}
return accumulator
}, [])

filteredLines.forEach(line => {
const lineNumber = parseInt(line, 10)
this._previousState[line] = Selectors.getLineFromBuffer(
Expand All @@ -87,26 +112,22 @@ export class SyntaxHighlightReconciler {

if (tokens.length) {
Log.verbose(
"[SyntaxHighlightReconciler] Applying changes to " + tokens.length + " lines.",
)
activeBuffer.updateHighlights(
this._tokenColors.tokenColors,
(highlightUpdater: any) => {
tokens.forEach(token => {
const { line, highlights } = token
if (Log.isDebugLoggingEnabled()) {
Log.debug(
"[SyntaxHighlightingReconciler] Updating tokens for line: " +
token.line +
" | " +
JSON.stringify(highlights),
)
}

highlightUpdater.setHighlightsForLine(line, highlights)
})
},
`[SyntaxHighlightReconciler] Applying changes to ${tokens.length} lines.`,
)
activeBuffer.updateHighlights(visibleTokens, highlightUpdater => {
tokens.forEach(token => {
const { line, highlights } = token
if (Log.isDebugLoggingEnabled()) {
Log.debug(
`[SyntaxHighlightingReconciler] Updating tokens for line: ${line} | ${prettyPrint(
highlights,
)}`,
)
}

highlightUpdater.setHighlightsForLine(line, highlights)
})
})
}
}
}
Expand All @@ -121,8 +142,7 @@ export class SyntaxHighlightReconciler {
}

private _getHighlightGroupFromScope(scopes: string[]): TokenColor {
const configurationColors = this._tokenColors.tokenColors
const highestRanked = this._tokenScorer.rankTokenScopes(scopes, configurationColors)
const highestRanked = this._tokenScorer.rankTokenScopes(scopes, this._tokenColors.tokenTree)
return highestRanked
}
}
28 changes: 20 additions & 8 deletions browser/src/Services/SyntaxHighlighting/SyntaxHighlighting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ import {
} from "./SyntaxHighlightingStore"

import { ISyntaxHighlighter } from "./ISyntaxHighlighter"
import { SyntaxHighlightReconciler } from "./SyntaxHighlightReconciler"
import {
IEditorWithSyntaxHighlighter,
SyntaxHighlightReconciler,
} from "./SyntaxHighlightReconciler"
import { getLineFromBuffer } from "./SyntaxHighlightSelectors"

import * as Utility from "./../../Utility"
Expand All @@ -45,7 +48,10 @@ export class SyntaxHighlighter implements ISyntaxHighlighter {
constructor(private _editor: NeovimEditor, private _tokenColors: TokenColors) {
this._store = createSyntaxHighlightStore()

this._reconciler = new SyntaxHighlightReconciler(this._editor, this._tokenColors)
this._reconciler = new SyntaxHighlightReconciler(
this._editor as IEditorWithSyntaxHighlighter,
this._tokenColors,
)
this._unsubscribe = this._store.subscribe(() => {
const state = this._store.getState()
this._reconciler.update(state)
Expand All @@ -62,12 +68,10 @@ export class SyntaxHighlighter implements ISyntaxHighlighter {
bottomLineInView: number,
): void {
Log.verbose(
"[SyntaxHighlighting.notifyViewportChanged] - bufferId: " +
bufferId +
" topLineInView: " +
topLineInView +
" bottomLineInView: " +
bottomLineInView,
`[SyntaxHighlighting.notifyViewportChanged] -
bufferId: ${bufferId}
topLineInView: ${topLineInView}
bottomLineInView: ${bottomLineInView}`,
)

const state = this._store.getState()
Expand All @@ -89,6 +93,10 @@ export class SyntaxHighlighter implements ISyntaxHighlighter {
})
}

public async notifyColorschemeRedraw(bufferId: string) {
this._store.dispatch({ type: "SYNTAX_RESET_BUFFER", bufferId })
}

public async notifyBufferUpdate(evt: Oni.EditorBufferChangedEventArgs): Promise<void> {
const firstChange = evt.contentChanges[0]
if (!firstChange.range && !firstChange.rangeLength) {
Expand Down Expand Up @@ -157,6 +165,10 @@ export class NullSyntaxHighlighter implements ISyntaxHighlighter {
return null
}

public notifyColorschemeRedraw(id: string): void {
return null
}

public notifyViewportChanged(
bufferId: string,
topLineInView: number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ export const bufferReducer: Reducer<IBufferSyntaxHighlightState> = (
action: ISyntaxHighlightAction,
) => {
switch (action.type) {
case "SYNTAX_RESET_BUFFER":
return {
...state,
lines: linesReducer(state.lines, action),
}
case "SYNTAX_UPDATE_BUFFER":
return {
...state,
Expand Down Expand Up @@ -125,6 +130,21 @@ export const linesReducer: Reducer<SyntaxHighlightLines> = (
}
return newState
}
case "SYNTAX_RESET_BUFFER":
const resetState = Object.entries(state).reduce<SyntaxHighlightLines>(
(newResetState, [lineNumber, line]) => {
newResetState[lineNumber] = {
tokens: [],
ruleStack: null,
...line,
dirty: true,
}
return newResetState
},
{},
)
return resetState

case "SYNTAX_UPDATE_BUFFER":
const updatedBufferState: SyntaxHighlightLines = {
...state,
Expand Down
20 changes: 14 additions & 6 deletions browser/src/Services/SyntaxHighlighting/SyntaxHighlightingStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ export const DefaultSyntaxHighlightState: ISyntaxHighlightState = {
}

export type ISyntaxHighlightAction =
| {
type: "SYNTAX_RESET_BUFFER"
bufferId: string
}
| {
type: "SYNTAX_UPDATE_BUFFER"
language: string
Expand Down Expand Up @@ -150,14 +154,14 @@ const updateBufferLineMiddleware = (store: any) => (next: any) => (action: any)
action.lineNumber === 0 ? null : buffer.lines[action.lineNumber - 1].ruleStack
const tokenizeResult = grammar.tokenizeLine(action.line, previousRuleStack)

const tokens = tokenizeResult.tokens.map((t: any) => ({
const tokens = tokenizeResult.tokens.map(token => ({
range: types.Range.create(
action.lineNumber,
t.startIndex,
token.startIndex,
action.lineNumber,
t.endIndex,
token.endIndex,
),
scopes: t.scopes,
scopes: token.scopes,
}))

const updateInsertLineAction: ISyntaxHighlightAction = {
Expand All @@ -180,7 +184,11 @@ const updateBufferLineMiddleware = (store: any) => (next: any) => (action: any)
const updateTokenMiddleware = (store: any) => (next: any) => (action: any) => {
const result: ISyntaxHighlightAction = next(action)

if (action.type === "SYNTAX_UPDATE_BUFFER" || action.type === "SYNTAX_UPDATE_BUFFER_VIEWPORT") {
if (
action.type === "SYNTAX_UPDATE_BUFFER" ||
action.type === "SYNTAX_UPDATE_BUFFER_VIEWPORT" ||
action.type === "SYNTAX_RESET_BUFFER"
) {
const state: ISyntaxHighlightState = store.getState()
const bufferId = action.bufferId

Expand Down Expand Up @@ -212,7 +220,7 @@ const updateTokenMiddleware = (store: any) => (next: any) => (action: any) => {

syntaxHighlightingJobs.startJob(
new SyntaxHighlightingPeriodicJob(
store as any,
store,
action.bufferId,
grammar,
relevantRange.top,
Expand Down
Loading