Skip to content

Commit

Permalink
API - Range: Add 'explode' method (onivim#291)
Browse files Browse the repository at this point in the history
* Factor range out of types

* Refactor Range to separate module

* Add interface

* Formatting

* Test cases for explode method
  • Loading branch information
bryphe authored Apr 29, 2019
1 parent 7e1520d commit b63174c
Show file tree
Hide file tree
Showing 16 changed files with 263 additions and 116 deletions.
2 changes: 2 additions & 0 deletions src/editor/Core/Oni_Core.re
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ module IndentationSettings = IndentationSettings;
module Theme = Theme;
module Keybindings = Keybindings;
module Filesystem = Filesystem;
module Range = Range;
module Ripgrep = Ripgrep;
module Tokenizer = Tokenizer;
module Uri = Uri;
module VisualRange = VisualRange;
78 changes: 78 additions & 0 deletions src/editor/Core/Range.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
open Types;

[@deriving show({with_path: false})]
type t = {
startPosition: Position.t,
endPosition: Position.t,
};

let createFromPositions = (~startPosition, ~endPosition, ()) => {
startPosition,
endPosition,
};

let create = (~startLine, ~startCharacter, ~endLine, ~endCharacter, ()) =>
createFromPositions(
~startPosition=Position.create(startLine, startCharacter),
~endPosition=Position.create(endLine, endCharacter),
(),
);

let zero =
create(
~startLine=ZeroBasedIndex(0),
~startCharacter=ZeroBasedIndex(0),
~endLine=ZeroBasedIndex(0),
~endCharacter=ZeroBasedIndex(0),
(),
);

let toZeroBasedPair = (v: Position.t) => {
(Index.toZeroBasedInt(v.line), Index.toZeroBasedInt(v.character));
};

let explode = (measure, v) => {
let (startLine, startCharacter) = v.startPosition |> toZeroBasedPair;
let (endLine, endCharacter) = v.endPosition |> toZeroBasedPair;

if (startLine == endLine) {
[v];
} else {
let idx = ref(startLine);

let ranges = ref([]);

while (idx^ < endLine) {
let i = idx^;

let startCharacter = i == startLine ? startCharacter : 0;
let endCharacter = max(0, measure(i) - 1);

ranges :=
[
create(
~startLine=ZeroBasedIndex(i),
~startCharacter=ZeroBasedIndex(startCharacter),
~endCharacter=ZeroBasedIndex(endCharacter),
~endLine=ZeroBasedIndex(i),
(),
),
...ranges^,
];

incr(idx);
};

[
create(
~startLine=ZeroBasedIndex(endLine),
~startCharacter=ZeroBasedIndex(0),
~endCharacter=ZeroBasedIndex(endCharacter),
~endLine=ZeroBasedIndex(endLine),
(),
),
...ranges^,
]
|> List.rev;
};
};
38 changes: 38 additions & 0 deletions src/editor/Core/Range.rei
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Range.rei
*
* Module dealing with Range (tuples of positions)
*/

open Types;

[@deriving show({with_path: false})]
type t = {
startPosition: Position.t,
endPosition: Position.t,
};

let createFromPositions:
(~startPosition: Position.t, ~endPosition: Position.t, unit) => t;

let create:
(
~startLine: Index.t,
~startCharacter: Index.t,
~endLine: Index.t,
~endCharacter: Index.t,
unit
) =>
t;

let zero: t;

/*
* explode(range, measure) takes a Range.t and a measurement function (int => int),
* and expands a multiple-line range into a list of ranges, where there there is
* a single range per-line.
*
* If the input range is a single line, a single item list with the input range
* will be returned.
*/
let explode: (int => int, t) => list(t);
86 changes: 0 additions & 86 deletions src/editor/Core/Types.re
Original file line number Diff line number Diff line change
Expand Up @@ -93,35 +93,6 @@ module Position = {
};
};

module Range = {
[@deriving show({with_path: false})]
type t = {
startPosition: Position.t,
endPosition: Position.t,
};

let createFromPositions = (~startPosition, ~endPosition, ()) => {
startPosition,
endPosition,
};

let create = (~startLine, ~startCharacter, ~endLine, ~endCharacter, ()) =>
createFromPositions(
~startPosition=Position.create(startLine, startCharacter),
~endPosition=Position.create(endLine, endCharacter),
(),
);

let zero =
create(
~startLine=ZeroBasedIndex(0),
~startCharacter=ZeroBasedIndex(0),
~endLine=ZeroBasedIndex(0),
~endCharacter=ZeroBasedIndex(0),
(),
);
};

[@deriving show({with_path: false})]
type buftype =
| Empty
Expand Down Expand Up @@ -294,60 +265,3 @@ module Input = {
command: string,
};
};

module VisualRange = {
[@deriving show({with_path: false})]
type mode =
| None
| Visual /* "v" */
| BlockwiseVisual /* "<C-v>" */
| LinewiseVisual; /* "V" */

[@deriving show({with_path: false})]
type t = {
range: Range.t,
mode,
};

let _modeFromString = s => {
switch (s) {
| "V" => LinewiseVisual
| "vb" => BlockwiseVisual
| "v" => Visual
| _ => None
};
};

/*
* The range might not always come through in the correct 'order' -
* this method normalizes the range so that the (startLine, startColumn) is
* before or equal to (endLine, endColumn)
*/
let _normalizeRange = (startLine, startColumn, endLine, endColumn) =>
if (startLine > endLine) {
(endLine, endColumn, startLine, startColumn);
} else if (startLine == endLine && startColumn > endColumn) {
(endLine, endColumn, startLine, startColumn);
} else {
(startLine, startColumn, endLine, endColumn);
};

let create =
(~startLine=1, ~startColumn=1, ~endLine=1, ~endColumn=1, ~mode="", ()) => {
let (startLine, startColumn, endLine, endColumn) =
_normalizeRange(startLine, startColumn, endLine, endColumn);

let range =
Range.create(
~startLine=OneBasedIndex(startLine),
~startCharacter=OneBasedIndex(startColumn),
~endLine=OneBasedIndex(endLine),
~endCharacter=OneBasedIndex(endColumn),
(),
);

let mode = _modeFromString(mode);

{range, mode};
};
};
54 changes: 54 additions & 0 deletions src/editor/Core/VisualRange.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
[@deriving show({with_path: false})]
type mode =
| None
| Visual /* "v" */
| BlockwiseVisual /* "<C-v>" */
| LinewiseVisual; /* "V" */

[@deriving show({with_path: false})]
type t = {
range: Range.t,
mode,
};

let _modeFromString = s => {
switch (s) {
| "V" => LinewiseVisual
| "vb" => BlockwiseVisual
| "v" => Visual
| _ => None
};
};

/*
* The range might not always come through in the correct 'order' -
* this method normalizes the range so that the (startLine, startColumn) is
* before or equal to (endLine, endColumn)
*/
let _normalizeRange = (startLine, startColumn, endLine, endColumn) =>
if (startLine > endLine) {
(endLine, endColumn, startLine, startColumn);
} else if (startLine == endLine && startColumn > endColumn) {
(endLine, endColumn, startLine, startColumn);
} else {
(startLine, startColumn, endLine, endColumn);
};

let create =
(~startLine=1, ~startColumn=1, ~endLine=1, ~endColumn=1, ~mode="", ()) => {
let (startLine, startColumn, endLine, endColumn) =
_normalizeRange(startLine, startColumn, endLine, endColumn);

let range =
Range.create(
~startLine=OneBasedIndex(startLine),
~startCharacter=OneBasedIndex(startColumn),
~endLine=OneBasedIndex(endLine),
~endCharacter=OneBasedIndex(endColumn),
(),
);

let mode = _modeFromString(mode);

{range, mode};
};
1 change: 0 additions & 1 deletion src/editor/Model/Diagnostics.re
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
*/

open Oni_Core;
open Oni_Core.Types;

module Diagnostic = {
type t = {range: Range.t};
Expand Down
2 changes: 1 addition & 1 deletion src/editor/Model/Diagnostics.rei
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* or minimap.
*/

open Oni_Core.Types;
open Oni_Core;

module Diagnostic: {
type t = {range: Range.t};
Expand Down
1 change: 1 addition & 0 deletions src/editor/Model/Selection.re
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* based on the visual selection state
*/

open Oni_Core;
open Oni_Core.Types;

let getRangesForLinewiseSelection = (startLine, endLine, buffer) => {
Expand Down
4 changes: 2 additions & 2 deletions src/editor/Neovim/Notification.re
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ type t =
| WildmenuShow(Wildmenu.t)
| WildmenuHide(Wildmenu.t)
| WildmenuSelected(int)
| VisualRangeUpdate(Core.Types.VisualRange.t)
| VisualRangeUpdate(Core.VisualRange.t)
| Ignored;

type commandlineInput = {input: string};
Expand Down Expand Up @@ -259,7 +259,7 @@ let parse = (t: string, msg: Msgpck.t) => {
]),
) =>
let visRange =
Core.Types.VisualRange.create(
Core.VisualRange.create(
~startLine,
~startColumn,
~endLine,
Expand Down
2 changes: 1 addition & 1 deletion src/editor/UI/EditorSurface.re
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ let createElement =
switch (activeBuffer) {
| Some(b) =>
let ranges = Selection.getRanges(editor.selection, b);
Oni_Core.Types.Range.(
Oni_Core.Range.(
List.iter(
(r: Range.t) => {
let line = Index.toZeroBasedInt(r.startPosition.line);
Expand Down
32 changes: 32 additions & 0 deletions test/editor/Core/Helpers.re
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
open Oni_Core;
open Oni_Core.Types;

exception OptionInvalidException(string);
let getOrThrow: option('a) => 'a =
v =>
Expand All @@ -21,3 +24,32 @@ let repeat = (~iterations: int=5, f) => {
count := count^ + 1;
};
};

let validateRange =
(
expect: Rely__DefaultMatchers.matchers(unit),
actualRange: Range.t,
expectedRange: Range.t,
) => {
expect.int(Index.toZeroBasedInt(actualRange.startPosition.line)).toBe(
Index.toZeroBasedInt(expectedRange.startPosition.line),
);
expect.int(Index.toZeroBasedInt(actualRange.endPosition.line)).toBe(
Index.toZeroBasedInt(expectedRange.endPosition.line),
);
expect.int(Index.toZeroBasedInt(actualRange.startPosition.character)).toBe(
Index.toZeroBasedInt(expectedRange.startPosition.character),
);
expect.int(Index.toZeroBasedInt(actualRange.endPosition.character)).toBe(
Index.toZeroBasedInt(expectedRange.endPosition.character),
);
};

let validateRanges =
(
expect: Rely__DefaultMatchers.matchers(unit),
actualRanges,
expectedRanges,
) => {
List.iter2(validateRange(expect), actualRanges, expectedRanges);
};
Loading

0 comments on commit b63174c

Please sign in to comment.