From 8f4a17ea0a37dea695fba023fba3dadd9c8158ab Mon Sep 17 00:00:00 2001 From: glennsl Date: Wed, 26 Feb 2020 21:52:49 +0100 Subject: [PATCH 1/8] convert CursorView to immediate mode --- src/Feature/Editor/CursorView.re | 48 ++++++++++++------------------- src/Feature/Editor/SurfaceView.re | 11 ++++++- 2 files changed, 28 insertions(+), 31 deletions(-) diff --git a/src/Feature/Editor/CursorView.re b/src/Feature/Editor/CursorView.re index bc951352a2..cfbf743030 100644 --- a/src/Feature/Editor/CursorView.re +++ b/src/Feature/Editor/CursorView.re @@ -1,18 +1,16 @@ open EditorCoreTypes; -open Revery; -open Revery.UI; open Oni_Core; -let make = +let render = ( + ~context, ~buffer, ~mode: Vim.Mode.t, ~isActiveSplit, ~editorFont: EditorFont.t, ~cursorPosition: Location.t, ~editor: Editor.t, - (), ) => { let cursorLine = Index.toZeroBased(cursorPosition.line); let lineCount = Buffer.getNumberOfLines(buffer); @@ -31,38 +29,28 @@ let make = (0, 1); }; + let x = + editorFont.measuredWidth *. float(cursorOffset) -. editor.scrollX +. 0.5; + + let y = + editorFont.measuredHeight + *. float(Index.toZeroBased(cursorPosition.line)) + -. editor.scrollY + +. 0.5; + let fullCursorWidth = - cursorCharacterWidth * int_of_float(editorFont.measuredWidth); + float(cursorCharacterWidth) *. editorFont.measuredWidth; - let cursorWidth = + let width = switch (mode, isActiveSplit) { - | (Insert, true) => 2 + | (Insert, true) => 2. | _ => fullCursorWidth }; - let cursorPixelY = - int_of_float( - editorFont.measuredHeight - *. float(Index.toZeroBased(cursorPosition.line)) - -. editor.scrollY - +. 0.5, - ); - - let cursorPixelX = - int_of_float( - editorFont.measuredWidth *. float(cursorOffset) -. editor.scrollX +. 0.5, - ); + let height = editorFont.measuredHeight; - let style = - Style.[ - position(`Absolute), - top(cursorPixelY), - left(cursorPixelX), - height(int_of_float(editorFont.measuredHeight)), - width(cursorWidth), - backgroundColor(Colors.white), - ]; - let cursorOpacity = isActiveSplit ? 0.5 : 0.25; + let opacity = isActiveSplit ? 0.5 : 0.25; + let color = Revery.Color.multiplyAlpha(opacity, Revery.Colors.white); - ; + Draw.rect(~context, ~x, ~y, ~width, ~height, ~color); }; diff --git a/src/Feature/Editor/SurfaceView.re b/src/Feature/Editor/SurfaceView.re index 3a34bd036a..33390be18d 100644 --- a/src/Feature/Editor/SurfaceView.re +++ b/src/Feature/Editor/SurfaceView.re @@ -177,9 +177,18 @@ let%component make = indentation, ); }; + + CursorView.render( + ~context, + ~buffer, + ~mode, + ~isActiveSplit, + ~cursorPosition, + ~editor, + ~editorFont, + ); }} /> - Date: Wed, 26 Feb 2020 22:33:10 +0100 Subject: [PATCH 2/8] invert color of text under cursor --- src/Feature/Editor/CursorView.re | 70 +++++++++++++++---------------- src/Feature/Editor/SurfaceView.re | 3 +- 2 files changed, 34 insertions(+), 39 deletions(-) diff --git a/src/Feature/Editor/CursorView.re b/src/Feature/Editor/CursorView.re index cfbf743030..f7bbf7ae10 100644 --- a/src/Feature/Editor/CursorView.re +++ b/src/Feature/Editor/CursorView.re @@ -4,53 +4,49 @@ open Oni_Core; let render = ( - ~context, + ~context: Draw.context, ~buffer, ~mode: Vim.Mode.t, ~isActiveSplit, - ~editorFont: EditorFont.t, ~cursorPosition: Location.t, - ~editor: Editor.t, + ~theme: Theme.t, ) => { - let cursorLine = Index.toZeroBased(cursorPosition.line); + let line = Index.toZeroBased(cursorPosition.line); + let column = Index.toZeroBased(cursorPosition.column); + let bufferLine = Buffer.getLine(line, buffer); let lineCount = Buffer.getNumberOfLines(buffer); - let (cursorOffset, cursorCharacterWidth) = - if (lineCount > 0 && cursorLine < lineCount) { - let cursorLine = Buffer.getLine(cursorLine, buffer); - - let (cursorOffset, width) = - BufferViewTokenizer.getCharacterPositionAndWidth( - cursorLine, - Index.toZeroBased(cursorPosition.column), - ); - (cursorOffset, width); + let (offset, characterWidth) = + if (lineCount > 0 && line < lineCount) { + BufferViewTokenizer.getCharacterPositionAndWidth(bufferLine, column); } else { (0, 1); }; - let x = - editorFont.measuredWidth *. float(cursorOffset) -. editor.scrollX +. 0.5; - - let y = - editorFont.measuredHeight - *. float(Index.toZeroBased(cursorPosition.line)) - -. editor.scrollY - +. 0.5; - - let fullCursorWidth = - float(cursorCharacterWidth) *. editorFont.measuredWidth; - - let width = - switch (mode, isActiveSplit) { - | (Insert, true) => 2. - | _ => fullCursorWidth + let x = float(offset) *. context.charWidth; + let y = float(line) *. context.lineHeight +. 0.5; + let height = context.lineHeight; + let color = Revery.Colors.white; + + switch (mode, isActiveSplit) { + | (Insert, true) => + let width = 2.; + Draw.rect(~context, ~x, ~y, ~width, ~height, ~color); + + | _ => + let width = float(characterWidth) *. context.charWidth; + Draw.rect(~context, ~x, ~y, ~width, ~height, ~color); + + switch (BufferLine.subExn(~index=offset, ~length=1, bufferLine)) { + | text => + Draw.shapedText( + ~context, + ~x=x -. 0.5, + ~y=y -. context.fontMetrics.ascent -. 0.5, + ~color=theme.editorBackground, + text, + ) + | exception _ => () }; - - let height = editorFont.measuredHeight; - - let opacity = isActiveSplit ? 0.5 : 0.25; - let color = Revery.Color.multiplyAlpha(opacity, Revery.Colors.white); - - Draw.rect(~context, ~x, ~y, ~width, ~height, ~color); + }; }; diff --git a/src/Feature/Editor/SurfaceView.re b/src/Feature/Editor/SurfaceView.re index 33390be18d..6fbf564ecb 100644 --- a/src/Feature/Editor/SurfaceView.re +++ b/src/Feature/Editor/SurfaceView.re @@ -184,8 +184,7 @@ let%component make = ~mode, ~isActiveSplit, ~cursorPosition, - ~editor, - ~editorFont, + ~theme, ); }} /> From 8276d751a86920ff419fb4839a6e483ac42781c4 Mon Sep 17 00:00:00 2001 From: glennsl Date: Wed, 26 Feb 2020 22:45:54 +0100 Subject: [PATCH 3/8] add cursor theme colors --- src/Core/Theme.re | 17 +++++++++++++++++ src/Feature/Editor/CursorView.re | 9 +++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/Core/Theme.re b/src/Core/Theme.re index 81f68f8d62..6d0e8da618 100644 --- a/src/Core/Theme.re +++ b/src/Core/Theme.re @@ -57,6 +57,8 @@ type t = { activityBarForeground: Color.t, editorBackground: Color.t, editorForeground: Color.t, + editorCursorBackground: Color.t, + editorCursorForeground: Color.t, editorHoverWidgetBackground: Color.t, editorHoverWidgetBorder: Color.t, editorLineHighlightBackground: Color.t, @@ -135,6 +137,8 @@ let default: t = { activityBarForeground: Color.hex("#DCDCDC"), editorBackground: Color.hex("#2F3440"), editorForeground: Color.hex("#DCDCDC"), + editorCursorBackground: Color.hex("#2F3440"), + editorCursorForeground: Color.hex("#DCDCDC"), editorFindMatchBackground: Color.hex("#42557b"), editorFindMatchBorder: Color.hex("#457dff"), editorFindMatchHighlightBackground: Color.hex("#314365"), @@ -223,6 +227,17 @@ let ofColorTheme = (uiTheme, ct: Textmate.ColorTheme.t) => { let editorForeground = getColor(defaultForeground, ["editor.foreground", "foreground"]); + let editorCursorBackground = + getColor( + defaultBackground, + ["editorCursor.background", "editor.background", "background"], + ); + let editorCursorForeground = + getColor( + defaultForeground, + ["editorCursor.foreground", "editor.foreground", "foreground"], + ); + let editorHoverWidgetBackground = getColor( defaultBackground, @@ -439,6 +454,8 @@ let ofColorTheme = (uiTheme, ct: Textmate.ColorTheme.t) => { activityBarForeground, editorBackground, editorForeground, + editorCursorBackground, + editorCursorForeground, editorHoverWidgetBackground, editorHoverWidgetBorder, editorIndentGuideBackground, diff --git a/src/Feature/Editor/CursorView.re b/src/Feature/Editor/CursorView.re index f7bbf7ae10..90b41f8b0e 100644 --- a/src/Feature/Editor/CursorView.re +++ b/src/Feature/Editor/CursorView.re @@ -26,16 +26,17 @@ let render = let x = float(offset) *. context.charWidth; let y = float(line) *. context.lineHeight +. 0.5; let height = context.lineHeight; - let color = Revery.Colors.white; + let background = theme.editorCursorBackground; + let foreground = theme.editorCursorForeground; switch (mode, isActiveSplit) { | (Insert, true) => let width = 2.; - Draw.rect(~context, ~x, ~y, ~width, ~height, ~color); + Draw.rect(~context, ~x, ~y, ~width, ~height, ~color=foreground); | _ => let width = float(characterWidth) *. context.charWidth; - Draw.rect(~context, ~x, ~y, ~width, ~height, ~color); + Draw.rect(~context, ~x, ~y, ~width, ~height, ~color=foreground); switch (BufferLine.subExn(~index=offset, ~length=1, bufferLine)) { | text => @@ -43,7 +44,7 @@ let render = ~context, ~x=x -. 0.5, ~y=y -. context.fontMetrics.ascent -. 0.5, - ~color=theme.editorBackground, + ~color=background, text, ) | exception _ => () From 5adf1e8ab94f8392d7fbfbeed5e6e08c1e4b5e8c Mon Sep 17 00:00:00 2001 From: glennsl Date: Thu, 27 Feb 2020 11:29:44 +0100 Subject: [PATCH 4/8] use column instead of offset for BufferLine.subExn --- src/Feature/Editor/CursorView.re | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Feature/Editor/CursorView.re b/src/Feature/Editor/CursorView.re index 90b41f8b0e..abd565b051 100644 --- a/src/Feature/Editor/CursorView.re +++ b/src/Feature/Editor/CursorView.re @@ -38,7 +38,7 @@ let render = let width = float(characterWidth) *. context.charWidth; Draw.rect(~context, ~x, ~y, ~width, ~height, ~color=foreground); - switch (BufferLine.subExn(~index=offset, ~length=1, bufferLine)) { + switch (BufferLine.subExn(~index=column, ~length=1, bufferLine)) { | text => Draw.shapedText( ~context, From 045be58c6f8a49248d1f7447532ee247cd75cbf6 Mon Sep 17 00:00:00 2001 From: glennsl Date: Thu, 27 Feb 2020 11:47:13 +0100 Subject: [PATCH 5/8] don't render whitespace --- src/Feature/Editor/BufferViewTokenizer.re | 6 ++---- src/Feature/Editor/CursorView.re | 5 ++++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Feature/Editor/BufferViewTokenizer.re b/src/Feature/Editor/BufferViewTokenizer.re index f258265e78..5d37891ac2 100644 --- a/src/Feature/Editor/BufferViewTokenizer.re +++ b/src/Feature/Editor/BufferViewTokenizer.re @@ -28,7 +28,7 @@ let tab = UChar.of_char('\t'); let cr = UChar.of_char('\r'); let lf = UChar.of_char('\n'); -let _isWhitespace = c => { +let isWhitespace = c => { UChar.eq(space, c) || UChar.eq(tab, c) || UChar.eq(cr, c) @@ -100,9 +100,7 @@ let tokenize = (~startIndex=0, ~endIndex, line, colorizer) => { let (bg1, fg1) = colorizer(i0); let (bg2, fg2) = colorizer(i1); - !colorEqual(bg1, bg2) - || !colorEqual(fg1, fg2) - || _isWhitespace(c0) != _isWhitespace(c1) + || isWhitespace(c0) != isWhitespace(c1) /* Always split on tabs */ || UChar.eq(c0, tab) || UChar.eq(c1, tab); diff --git a/src/Feature/Editor/CursorView.re b/src/Feature/Editor/CursorView.re index abd565b051..255de26d5c 100644 --- a/src/Feature/Editor/CursorView.re +++ b/src/Feature/Editor/CursorView.re @@ -39,6 +39,10 @@ let render = Draw.rect(~context, ~x, ~y, ~width, ~height, ~color=foreground); switch (BufferLine.subExn(~index=column, ~length=1, bufferLine)) { + | exception _ + | "" => () + | text when BufferViewTokenizer.isWhitespace(ZedBundled.get(text, 0)) => + () | text => Draw.shapedText( ~context, @@ -47,7 +51,6 @@ let render = ~color=background, text, ) - | exception _ => () }; }; }; From 7bab8b1858c8e9267424b8c8cf8b0f0c71976a0d Mon Sep 17 00:00:00 2001 From: glennsl Date: Thu, 27 Feb 2020 11:48:07 +0100 Subject: [PATCH 6/8] clean up BufferViewToenizer --- src/Feature/Editor/BufferViewTokenizer.re | 34 ++++++----------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/src/Feature/Editor/BufferViewTokenizer.re b/src/Feature/Editor/BufferViewTokenizer.re index 5d37891ac2..0f8783f1e6 100644 --- a/src/Feature/Editor/BufferViewTokenizer.re +++ b/src/Feature/Editor/BufferViewTokenizer.re @@ -35,23 +35,11 @@ let isWhitespace = c => { || UChar.eq(lf, c); }; -let _isNonWhitespace = c => !_isWhitespace(c); +let filterRuns = (r: Tokenizer.TextRun.t) => ZedBundled.length(r.text) != 0; -let filterRuns = (r: Tokenizer.TextRun.t) => { - let len = ZedBundled.length(r.text); - - if (len == 0) { - false; - } else { - true; - }; -}; - -type colorizer = int => (Color.t, Color.t); - -let textRunToToken = (colorizer: colorizer, r: Tokenizer.TextRun.t) => { +let textRunToToken = (colorizer, r: Tokenizer.TextRun.t) => { let startIndex = Index.toZeroBased(r.startIndex); - let (bg, fg) = colorizer(startIndex); + let (backgroundColor, color) = colorizer(startIndex); let firstChar = ZedBundled.get(r.text, 0); @@ -64,10 +52,7 @@ let textRunToToken = (colorizer: colorizer, r: Tokenizer.TextRun.t) => { Text; }; - let color = fg; - let backgroundColor = bg; - - let ret: t = { + { tokenType, text: r.text, startPosition: r.startPosition, @@ -75,7 +60,6 @@ let textRunToToken = (colorizer: colorizer, r: Tokenizer.TextRun.t) => { color, backgroundColor, }; - ret; }; let getCharacterPositionAndWidth = (~viewOffset: int=0, line: BufferLine.t, i) => { @@ -91,15 +75,13 @@ let getCharacterPositionAndWidth = (~viewOffset: int=0, line: BufferLine.t, i) = (actualOffset, width); }; -let colorEqual = (c1: Color.t, c2: Color.t) => { - Color.equals(c1, c2); -}; - let tokenize = (~startIndex=0, ~endIndex, line, colorizer) => { let split = (i0, c0, i1, c1) => { - let (bg1, fg1) = colorizer(i0); - let (bg2, fg2) = colorizer(i1); + let (bg0, fg0) = colorizer(i0); + let (bg1, fg1) = colorizer(i1); + !Color.equals(bg0, bg1) + || !Color.equals(fg0, fg1) || isWhitespace(c0) != isWhitespace(c1) /* Always split on tabs */ || UChar.eq(c0, tab) From e03047ef0045400f6bc229e67389670ee1d73e2d Mon Sep 17 00:00:00 2001 From: glennsl Date: Thu, 27 Feb 2020 11:50:58 +0100 Subject: [PATCH 7/8] remove unused Cursor module from Oni_Core --- src/Core/Cursor.re | 1 - src/Core/Oni_Core.re | 1 - 2 files changed, 2 deletions(-) delete mode 100644 src/Core/Cursor.re diff --git a/src/Core/Cursor.re b/src/Core/Cursor.re deleted file mode 100644 index 842a52c1dc..0000000000 --- a/src/Core/Cursor.re +++ /dev/null @@ -1 +0,0 @@ -type move = (~column: int, ~line: int) => unit; diff --git a/src/Core/Oni_Core.re b/src/Core/Oni_Core.re index 59344d8d99..07a923f57f 100644 --- a/src/Core/Oni_Core.re +++ b/src/Core/Oni_Core.re @@ -18,7 +18,6 @@ module ConfigurationParser = ConfigurationParser; module ConfigurationTransformer = ConfigurationTransformer; module ConfigurationValues = ConfigurationValues; module Constants = Constants; -module Cursor = Cursor; module Diff = Diff; module EditorFont = EditorFont; module EditorSize = EditorSize; From 95cfb09ba3b0a3bb3aaea6dfad74ad7dd60a2d65 Mon Sep 17 00:00:00 2001 From: glennsl Date: Thu, 27 Feb 2020 16:22:46 +0100 Subject: [PATCH 8/8] don't crash --- src/Feature/Editor/CursorView.re | 62 ++++++++++++++++---------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/Feature/Editor/CursorView.re b/src/Feature/Editor/CursorView.re index 255de26d5c..04a46ab360 100644 --- a/src/Feature/Editor/CursorView.re +++ b/src/Feature/Editor/CursorView.re @@ -13,44 +13,44 @@ let render = ) => { let line = Index.toZeroBased(cursorPosition.line); let column = Index.toZeroBased(cursorPosition.column); - let bufferLine = Buffer.getLine(line, buffer); let lineCount = Buffer.getNumberOfLines(buffer); - let (offset, characterWidth) = - if (lineCount > 0 && line < lineCount) { + if (lineCount <= 0 || line >= lineCount) { + (); + } else { + let bufferLine = Buffer.getLine(line, buffer); + let (offset, characterWidth) = BufferViewTokenizer.getCharacterPositionAndWidth(bufferLine, column); - } else { - (0, 1); - }; - let x = float(offset) *. context.charWidth; - let y = float(line) *. context.lineHeight +. 0.5; - let height = context.lineHeight; - let background = theme.editorCursorBackground; - let foreground = theme.editorCursorForeground; + let x = float(offset) *. context.charWidth; + let y = float(line) *. context.lineHeight +. 0.5; + let height = context.lineHeight; + let background = theme.editorCursorBackground; + let foreground = theme.editorCursorForeground; - switch (mode, isActiveSplit) { - | (Insert, true) => - let width = 2.; - Draw.rect(~context, ~x, ~y, ~width, ~height, ~color=foreground); + switch (mode, isActiveSplit) { + | (Insert, true) => + let width = 2.; + Draw.rect(~context, ~x, ~y, ~width, ~height, ~color=foreground); - | _ => - let width = float(characterWidth) *. context.charWidth; - Draw.rect(~context, ~x, ~y, ~width, ~height, ~color=foreground); + | _ => + let width = float(characterWidth) *. context.charWidth; + Draw.rect(~context, ~x, ~y, ~width, ~height, ~color=foreground); - switch (BufferLine.subExn(~index=column, ~length=1, bufferLine)) { - | exception _ - | "" => () - | text when BufferViewTokenizer.isWhitespace(ZedBundled.get(text, 0)) => - () - | text => - Draw.shapedText( - ~context, - ~x=x -. 0.5, - ~y=y -. context.fontMetrics.ascent -. 0.5, - ~color=background, - text, - ) + switch (BufferLine.subExn(~index=column, ~length=1, bufferLine)) { + | exception _ + | "" => () + | text when BufferViewTokenizer.isWhitespace(ZedBundled.get(text, 0)) => + () + | text => + Draw.shapedText( + ~context, + ~x=x -. 0.5, + ~y=y -. context.fontMetrics.ascent -. 0.5, + ~color=background, + text, + ) + }; }; }; };