diff --git a/src/editor/Core/Actions.re b/src/editor/Core/Actions.re
index 345e628c21..2c3f65802b 100644
--- a/src/editor/Core/Actions.re
+++ b/src/editor/Core/Actions.re
@@ -4,10 +4,10 @@
* Encapsulates actions that can impact the editor state
*/
-open State;
open Types;
type t =
+ | BufferUpdate(BufferUpdate.t)
| ChangeMode(Mode.t)
| SetEditorFont(EditorFont.t)
| Noop;
diff --git a/src/editor/Core/Buffer.re b/src/editor/Core/Buffer.re
index cf868263d6..73d1d08297 100644
--- a/src/editor/Core/Buffer.re
+++ b/src/editor/Core/Buffer.re
@@ -4,6 +4,8 @@
* In-memory text buffer representation
*/
+open Types;
+
type t = {
file: option(string),
lines: array(string),
@@ -13,3 +15,43 @@ let ofLines = (lines: array(string)) => {
let ret: t = {file: None, lines};
ret;
};
+
+let slice = (~lines: array(string), ~start, ~length, ()) => {
+ let len = Array.length(lines);
+ if (start >= len) {
+ [||];
+ } else {
+ let len = min(start + length, len) - start;
+ if (len <= 0) {
+ [||];
+ } else {
+ Array.sub(lines, start, len);
+ };
+ };
+};
+
+let applyUpdate = (lines: array(string), update: BufferUpdate.t) => {
+
+ if (update.endLine <= update.startLine) {
+ Array.of_list(update.lines)
+ } else {
+
+ let prev = slice(~lines, ~start=0, ~length=update.startLine, ());
+ let post =
+ slice(
+ ~lines,
+ ~start=update.endLine,
+ ~length=Array.length(lines) - update.endLine,
+ (),
+ );
+
+ let lines = Array.of_list(update.lines);
+
+ Array.concat([prev, lines, post]);
+ }
+};
+
+let update = (buf: t, update: BufferUpdate.t) => {
+ let ret: t = {...buf, lines: applyUpdate(buf.lines, update)};
+ ret;
+};
diff --git a/src/editor/Core/Reducer.re b/src/editor/Core/Reducer.re
index e6fa492c26..34fd6967ea 100644
--- a/src/editor/Core/Reducer.re
+++ b/src/editor/Core/Reducer.re
@@ -12,6 +12,7 @@ let reduce: (State.t, Actions.t) => State.t =
| ChangeMode(m) =>
let ret: State.t = {...s, mode: m};
ret;
+ | BufferUpdate(bu) => {...s, buffer: Buffer.update(s.buffer, bu)}
| SetEditorFont(font) => {...s, editorFont: font}
| Noop => s
};
diff --git a/src/editor/Core/State.re b/src/editor/Core/State.re
index 023801435b..7534a12606 100644
--- a/src/editor/Core/State.re
+++ b/src/editor/Core/State.re
@@ -5,21 +5,6 @@
*/
open Types;
-
-module Mode = {
- type t =
- | Insert
- | Normal
- | Other;
-
- let show = v =>
- switch (v) {
- | Insert => "insert"
- | Normal => "normal"
- | Other => "unknown"
- };
-};
-
module Tab = {
type t = {
id: int,
@@ -33,12 +18,14 @@ module Tab = {
type t = {
mode: Mode.t,
tabs: list(Tab.t),
+ buffer: Buffer.t,
editorFont: EditorFont.t,
};
let create: unit => t =
() => {
mode: Insert,
+ buffer: Buffer.ofLines([|"testing"|]),
editorFont:
EditorFont.create(
~fontFile="FiraCode-Regular.ttf",
diff --git a/src/editor/Core/Types.re b/src/editor/Core/Types.re
index c121b42d11..2b275507b2 100644
--- a/src/editor/Core/Types.re
+++ b/src/editor/Core/Types.re
@@ -10,6 +10,34 @@ module Position = {
};
};
+module Mode = {
+ type t =
+ | Insert
+ | Normal
+ | Other;
+
+ let show = v =>
+ switch (v) {
+ | Insert => "insert"
+ | Normal => "normal"
+ | Other => "unknown"
+ };
+};
+
+module BufferUpdate = {
+ type t = {
+ startLine: int,
+ endLine: int,
+ lines: list(string),
+ };
+
+ let create = (~startLine, ~endLine, ~lines, ()) => {
+ startLine,
+ endLine,
+ lines,
+ };
+};
+
module EditorFont = {
type t = {
fontFile: string,
diff --git a/src/editor/UI/EditorSurface.re b/src/editor/UI/EditorSurface.re
index 4b5df2e0c6..401bdb9ee8 100644
--- a/src/editor/UI/EditorSurface.re
+++ b/src/editor/UI/EditorSurface.re
@@ -69,12 +69,7 @@ let make = (state: State.t) =>
component((_slots: React.Hooks.empty) => {
let theme = Theme.get();
- let bufferView =
- Buffer.ofLines([|
- "- Hello from line 1",
- "- Hello from line 2",
- "--- Hello from line 3",
- |])
+ let bufferView = state.buffer
|> TokenizedBuffer.ofBuffer
|> TokenizedBufferView.ofTokenizedBuffer;
@@ -91,7 +86,6 @@ let make = (state: State.t) =>
color(theme.foreground),
flexGrow(1),
];
- /* flexShrink(1), */
...textElements ;
});
diff --git a/src/editor/UI/StatusBar.re b/src/editor/UI/StatusBar.re
index 6229df7129..d367a1cdaa 100644
--- a/src/editor/UI/StatusBar.re
+++ b/src/editor/UI/StatusBar.re
@@ -25,10 +25,10 @@ let viewStyle =
alignItems(`Center),
];
-let make = (~mode: State.Mode.t, ()) =>
+let make = (~mode: Types.Mode.t, ()) =>
component((_slots: React.Hooks.empty) =>
-
+
);
diff --git a/src/editor/bin/Oni2.re b/src/editor/bin/Oni2.re
index c808ed3b0f..31dd2e9c6c 100644
--- a/src/editor/bin/Oni2.re
+++ b/src/editor/bin/Oni2.re
@@ -40,7 +40,7 @@ let init = app => {
let state: Core.State.t = App.getState(app);
prerr_endline(
"[DEBUG - STATE] Mode: "
- ++ Core.State.Mode.show(state.mode)
+ ++ Core.Types.Mode.show(state.mode)
++ " editor font measured width: "
++ string_of_int(state.editorFont.measuredWidth)
++ " editor font measured height: "
@@ -154,6 +154,7 @@ let init = app => {
| ModeChanged("normal") => Core.Actions.ChangeMode(Normal)
| ModeChanged("insert") => Core.Actions.ChangeMode(Insert)
| ModeChanged(_) => Core.Actions.ChangeMode(Other)
+ | BufferLines(bc) => Core.Actions.BufferUpdate(Core.Types.BufferUpdate.create(~startLine=bc.firstLine, ~endLine=bc.lastLine, ~lines=bc.lines, ()))
| _ => Noop
};
diff --git a/test/editor/Core/BufferTests.re b/test/editor/Core/BufferTests.re
new file mode 100644
index 0000000000..14507fc345
--- /dev/null
+++ b/test/editor/Core/BufferTests.re
@@ -0,0 +1,37 @@
+/* open Oni_Core; */
+open TestFramework;
+
+open Helpers;
+
+open Oni_Core.Types;
+module Buffer = Oni_Core.Buffer;
+
+describe("update", ({test, _}) => {
+ test("empty buffer w/ update", ({expect}) => {
+ let buffer = Buffer.ofLines([||]);
+ let update = BufferUpdate.create(~startLine=0, ~endLine=1, ~lines=["a"], ());
+ let updatedBuffer = Buffer.update(buffer, update);
+ validateBuffer(expect, updatedBuffer, [|"a"|]);
+ });
+
+ test("update single line", ({expect}) => {
+ let buffer = Buffer.ofLines([|"a"|]);
+ let update = BufferUpdate.create(~startLine=0, ~endLine=1, ~lines=["abc"], ());
+ let updatedBuffer = Buffer.update(buffer, update);
+ validateBuffer(expect, updatedBuffer, [|"abc"|]);
+ });
+
+ test("delete line", ({expect}) => {
+ let buffer = Buffer.ofLines([|"a"|]);
+ let update = BufferUpdate.create(~startLine=0, ~endLine=1, ~lines=[], ());
+ let updatedBuffer = Buffer.update(buffer, update);
+ validateBuffer(expect, updatedBuffer, [||]);
+ });
+
+ test("update single line", ({expect}) => {
+ let buffer = Buffer.ofLines([|"a", "b", "c"|]);
+ let update = BufferUpdate.create(~startLine=1, ~endLine=2, ~lines=["d", "e", "f"], ());
+ let updatedBuffer = Buffer.update(buffer, update);
+ validateBuffer(expect, updatedBuffer, [|"a", "d", "e", "f", "c"|]);
+ });
+});
diff --git a/test/editor/Core/Helpers.re b/test/editor/Core/Helpers.re
index 1534401b14..eb4c597008 100644
--- a/test/editor/Core/Helpers.re
+++ b/test/editor/Core/Helpers.re
@@ -1,6 +1,8 @@
open Oni_Core;
open Oni_Core.Types;
+module Buffer = Oni_Core.Buffer;
+
let validateToken =
(
expect: Rely__DefaultMatchers.matchers(unit),
@@ -30,3 +32,22 @@ let validateTokens =
List.iter2(f, actualTokens, expectedTokens);
};
+
+let validateBuffer =
+ (
+ expect: Rely__DefaultMatchers.matchers(unit),
+ actualBuffer: Buffer.t,
+ expectedLines: array(string),
+ ) => {
+ expect.int(Array.length(actualBuffer.lines)).toBe(Array.length(expectedLines));
+
+ let validateLine = (actualLine, expectedLine) => {
+ expect.string(actualLine).toEqual(expectedLine);
+ }
+
+ let f = (actual, expected) => {
+ validateLine(actual, expected);
+ };
+
+ Array.iter2(f, actualBuffer.lines, expectedLines);
+};