Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the next/previous editor commands and keybindings #1447

Merged
merged 3 commits into from
Mar 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
59 changes: 54 additions & 5 deletions src/Model/EditorGroup.re
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,23 @@ let getOrCreateEditorForBuffer = (state, bufferId) => {
};
};

// TODO: Just use List.find_opt?
let rec _getIndexOfElement = elem =>
fun
| [] => (-1)
| [hd, ...tl] => hd === elem ? 0 : _getIndexOfElement(elem, tl) + 1;
| [] => None
| [hd, ...tl] =>
hd === elem
? Some(0)
: (
switch (_getIndexOfElement(elem, tl)) {
| None => None
| Some(i) => Some(i + 1)
}
Comment on lines +71 to +74
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use Option.map for this:

Suggested change
switch (_getIndexOfElement(elem, tl)) {
| None => None
| Some(i) => Some(i + 1)
}
_getIndexOfElement(elem, tl) |> Option.map(succ)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured there had to be something for that like in Rust but when looking at the Reason docs I did not see much. I need to check the OCaml docs more I suppose. Good tip with using succ too.

);

let _getAdjacentEditor = (editor: int, reverseTabOrder: list(int)) => {
switch (_getIndexOfElement(editor, reverseTabOrder)) {
| (-1) => None
| idx =>
| None => None
| Some(idx) =>
switch (
List.nth_opt(reverseTabOrder, idx + 1),
List.nth_opt(reverseTabOrder, max(idx - 1, 0)),
Expand All @@ -82,6 +89,48 @@ let _getAdjacentEditor = (editor: int, reverseTabOrder: list(int)) => {
};
};

let setActiveEditorTo = (kind, model) =>
switch (model.reverseTabOrder) {
| []
| [_] => model
| _ =>
switch (model.activeEditorId) {
| Some(activeEditorId) =>
switch (_getIndexOfElement(activeEditorId, model.reverseTabOrder)) {
| None => model
| Some(idx) =>
// The diff amounts are inverted because the list is in reverse order
let newIndex =
switch (kind) {
| `Next => idx - 1
| `Previous => idx + 1
};

let count = List.length(model.reverseTabOrder);

let newIndex =
if (newIndex < 0) {
// Wrapping negative, go to end
count - 1;
} else if (newIndex >= count) {
0;
// If this is past the end, go to zero
} else {
newIndex;
};
Comment on lines +111 to +120
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some convenience functions in Core.Utility.IndexEx for this:

let prevRollOver = (~first=0, ~last, current) =>
if (first >= last) {
first;
} else if (current <= first) {
last;
} else {
current - 1;
};
let prevRollOverOpt = (~first=0, ~last) =>
fun
| Some(index) => Some(prevRollOver(index, ~first, ~last))
| None => Some(last);
let nextRollOver = (~first=0, ~last, current) =>
if (first >= last) {
first;
} else if (current >= last) {
first;
} else {
current + 1;
};
let nextRollOverOpt = (~first=0, ~last) =>
fun
| Some(index) => Some(nextRollOver(index, ~first, ~last))
| None => Some(first);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that is exactly what I need. I'll give it a try when I get a chance.


{
...model,
activeEditorId: List.nth_opt(model.reverseTabOrder, newIndex),
};
}
| None => model
}
};

let nextEditor = setActiveEditorTo(`Next);
let previousEditor = setActiveEditorTo(`Previous);

let isEmpty = model => IntMap.is_empty(model.editors);

let removeEditorById = (state, editorId) => {
Expand Down
2 changes: 2 additions & 0 deletions src/Model/EditorGroup.rei
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ let getActiveEditor: t => option(Feature_Editor.Editor.t);
let setActiveEditor: (t, int) => t;
let getEditorById: (int, t) => option(Feature_Editor.Editor.t);
let getOrCreateEditorForBuffer: (t, int) => (t, Feature_Editor.EditorId.t);
let nextEditor: t => t;
let previousEditor: t => t;
let removeEditorById: (t, int) => t;

let isEmpty: t => bool;
3 changes: 3 additions & 0 deletions src/Model/EditorGroupReducer.re
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ let reduce = (v: EditorGroup.t, action: Actions.t) => {
let (newState, activeEditorId) =
EditorGroup.getOrCreateEditorForBuffer(v, id);
{...newState, activeEditorId: Some(activeEditorId)};
| Command("workbench.action.nextEditor") => EditorGroup.nextEditor(v)
| Command("workbench.action.previousEditor") =>
EditorGroup.previousEditor(v)
| ViewCloseEditor(id) => EditorGroup.removeEditorById(v, id)
| ViewSetActiveEditor(id) =>
switch (IntMap.find_opt(id, v.editors)) {
Expand Down
12 changes: 12 additions & 0 deletions src/Store/CommandStoreConnector.re
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,18 @@ let createDefaultCommands = getState => {
~action=Command("view.closeEditor"),
(),
),
Command.create(
~category=Some("View"),
~name="Open Next Editor",
~action=Command("workbench.action.nextEditor"),
(),
),
Command.create(
~category=Some("View"),
~name="Open Previous Editor",
~action=Command("workbench.action.previousEditor"),
(),
),
Command.create(
~category=Some("View"),
~name="Toggle Problems (Errors, Warnings)",
Expand Down
20 changes: 20 additions & 0 deletions src/Store/KeyBindingsStoreConnector.re
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,26 @@ let start = () => {
command: "view.closeEditor",
condition: WhenExpr.Value(True),
},
{
key: "<C-PAGEDOWN>",
command: "workbench.action.nextEditor",
condition: WhenExpr.Value(True),
},
{
key: "<D-S-]>",
command: "workbench.action.nextEditor",
condition: WhenExpr.Value(True),
},
{
key: "<C-PAGEUP>",
command: "workbench.action.previousEditor",
condition: WhenExpr.Value(True),
},
{
key: "<D-S-[>",
command: "workbench.action.previousEditor",
condition: WhenExpr.Value(True),
},
];

let reloadConfigOnWritePost = (~configPath, dispatch) => {
Expand Down
8 changes: 8 additions & 0 deletions src/Store/VimStoreConnector.re
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,14 @@ let start =
)
| ViewSetActiveEditor(_) => (state, synchronizeEditorEffect(state))
| ViewCloseEditor(_) => (state, synchronizeEditorEffect(state))
| Command("workbench.action.nextEditor") => (
state,
synchronizeEditorEffect(state),
)
| Command("workbench.action.previousEditor") => (
state,
synchronizeEditorEffect(state),
)
| KeyboardInput(s) => (state, inputEffect(s))
| CopyActiveFilepathToClipboard => (
state,
Expand Down