Skip to content

Commit

Permalink
State: Initial buffer state (onivim#27)
Browse files Browse the repository at this point in the history
* Add test case for buffer updates

* Fix circular type dependency

* Formatting

* Hook up state buffer to view

* Hook up Neovim's buffer updates to Oni's editor state
  • Loading branch information
bryphe authored Feb 6, 2019
1 parent 87bc8f5 commit d816250
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/editor/Core/Actions.re
Original file line number Diff line number Diff line change
Expand Up @@ -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;
42 changes: 42 additions & 0 deletions src/editor/Core/Buffer.re
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* In-memory text buffer representation
*/

open Types;

type t = {
file: option(string),
lines: array(string),
Expand All @@ -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;
};
1 change: 1 addition & 0 deletions src/editor/Core/Reducer.re
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
Expand Down
17 changes: 2 additions & 15 deletions src/editor/Core/State.re
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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",
Expand Down
28 changes: 28 additions & 0 deletions src/editor/Core/Types.re
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 1 addition & 7 deletions src/editor/UI/EditorSurface.re
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -91,7 +86,6 @@ let make = (state: State.t) =>
color(theme.foreground),
flexGrow(1),
];
/* flexShrink(1), */

<View style> ...textElements </View>;
});
Expand Down
4 changes: 2 additions & 2 deletions src/editor/UI/StatusBar.re
Original file line number Diff line number Diff line change
Expand Up @@ -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) =>
<View style=viewStyle>
<Text style=textStyle text={State.Mode.show(mode)} />
<Text style=textStyle text={Types.Mode.show(mode)} />
</View>
);

Expand Down
3 changes: 2 additions & 1 deletion src/editor/bin/Oni2.re
Original file line number Diff line number Diff line change
Expand Up @@ -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: "
Expand Down Expand Up @@ -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
};

Expand Down
37 changes: 37 additions & 0 deletions test/editor/Core/BufferTests.re
Original file line number Diff line number Diff line change
@@ -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"|]);
});
});
21 changes: 21 additions & 0 deletions test/editor/Core/Helpers.re
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
open Oni_Core;
open Oni_Core.Types;

module Buffer = Oni_Core.Buffer;

let validateToken =
(
expect: Rely__DefaultMatchers.matchers(unit),
Expand Down Expand Up @@ -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);
};

0 comments on commit d816250

Please sign in to comment.