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

feat(autoindent): On-Type auto-indent #2017

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
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
55 changes: 47 additions & 8 deletions src/Core/LanguageConfiguration.re
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,34 @@ module BracketPair = {
let endsWithOpenPair = ({openPair, _}, str) => {
StringEx.endsWith(~postfix=openPair, str);
};

let isJustClosingPair = ({closePair, _}, str) => {
let len = String.length(str);

let rec loop = (foundPair, idx) =>
if (idx >= len) {
foundPair;
} else if (foundPair) {
false;
// We found the closing pair... but there's other stuff after
} else {
let c = str.[idx];

if (c == ' ' || c == '\t') {
loop(foundPair, idx + 1);
} else if (c == closePair.[0]) {
loop(true, idx + 1);
} else {
false;
};
};

if (String.length(closePair) == 1) {
loop(false, 0);
} else {
false;
};
};
};

let defaultBrackets: list(BracketPair.t) =
Expand Down Expand Up @@ -226,9 +254,9 @@ let toVimAutoClosingPairs = (syntaxScope: SyntaxScope.t, configuration: t) => {
);
};

let toAutoIndent =
let toOpenAutoIndent =
(
{increaseIndentPattern, decreaseIndentPattern, brackets, _},
{increaseIndentPattern, brackets, _},
~previousLine as str,
~beforePreviousLine as _,
) => {
Expand All @@ -246,16 +274,27 @@ let toAutoIndent =
)
|> Option.value(~default=false);

if (increase) {Vim.AutoIndent.IncreaseIndent} else {
Vim.AutoIndent.KeepIndent
};
};

let toTypeAutoIndent = ({decreaseIndentPattern, brackets, _}, str) => {
let decrease =
decreaseIndentPattern
|> Option.map(regex => OnigRegExp.test(str, regex))
// If no indentation pattern, fall-back to bracket pair
|> OptionEx.or_lazy(() => {
Some(
List.exists(
bracket => BracketPair.isJustClosingPair(bracket, str),
brackets,
),
)
})
|> Option.value(~default=false);

if (increase) {
Vim.AutoIndent.IncreaseIndent;
} else if (decrease) {
Vim.AutoIndent.DecreaseIndent;
} else {
Vim.AutoIndent.KeepIndent;
if (decrease) {Vim.AutoIndent.DecreaseIndent} else {
Vim.AutoIndent.KeepIndent
};
};
4 changes: 3 additions & 1 deletion src/Core/LanguageConfiguration.rei
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ let decode: Json.decoder(t);

let toVimAutoClosingPairs: (SyntaxScope.t, t) => Vim.AutoClosingPairs.t;

let toAutoIndent:
let toOpenAutoIndent:
(t, ~previousLine: string, ~beforePreviousLine: option(string)) =>
Vim.AutoIndent.action;

let toTypeAutoIndent: (t, string) => Vim.AutoIndent.action;
40 changes: 17 additions & 23 deletions src/Model/VimContext.re
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ module Internal = {
|> Option.value(~default=SyntaxScope.none);
};

let autoClosingPairs = (~syntaxScope, ~maybeLanguageConfig, state: State.t) => {
let autoClosingPairs = (~syntaxScope, ~languageConfig, state: State.t) => {
let acpEnabled =
Configuration.getValue(
c => c.editorAutoClosingBrackets,
Expand All @@ -38,21 +38,15 @@ module Internal = {
);

if (acpEnabled) {
maybeLanguageConfig
|> Option.map(
LanguageConfiguration.toVimAutoClosingPairs(syntaxScope),
)
|> Option.value(~default=Vim.AutoClosingPairs.empty);
languageConfig
|> LanguageConfiguration.toVimAutoClosingPairs(syntaxScope);
} else {
Vim.AutoClosingPairs.empty;
};
};

let lineComment = (~maybeLanguageConfig) => {
maybeLanguageConfig
|> OptionEx.flatMap((config: LanguageConfiguration.t) =>
config.lineComment
);
let lineComment = (~languageConfig: LanguageConfiguration.t) => {
languageConfig.lineComment;
};

let indentation = (~buffer) =>
Expand All @@ -67,30 +61,29 @@ let current = (state: State.t) => {
let cursors = Editor.getVimCursors(editor);

let editorBuffer = Selectors.getActiveBuffer(state);
let maybeLanguageConfig: option(LanguageConfiguration.t) =
let languageConfig: LanguageConfiguration.t =
editorBuffer
|> OptionEx.flatMap(Buffer.getFileType)
|> OptionEx.flatMap(
Ext.LanguageInfo.getLanguageConfiguration(state.languageInfo),
);
)
|> Option.value(~default=LanguageConfiguration.default);

let maybeCursor =
switch (Editor.getVimCursors(editor)) {
| [hd, ..._] => Some(hd)
| [] => None
};

// TODO: Hook up to Vim context
let autoIndent =
maybeLanguageConfig
|> Option.map(LanguageConfiguration.toAutoIndent)
|> Option.value(~default=(~previousLine as _, ~beforePreviousLine as _) =>
Vim.AutoIndent.KeepIndent
);
let onOpenAutoIndent =
languageConfig |> LanguageConfiguration.toOpenAutoIndent;

let onTypeAutoIndent =
languageConfig |> LanguageConfiguration.toTypeAutoIndent;

let syntaxScope = Internal.syntaxScope(~cursor=maybeCursor, state);
let autoClosingPairs =
Internal.autoClosingPairs(~syntaxScope, ~maybeLanguageConfig, state);
Internal.autoClosingPairs(~syntaxScope, ~languageConfig, state);

let Feature_Editor.EditorLayout.{
bufferHeightInCharacters: height,
Expand All @@ -109,14 +102,15 @@ let current = (state: State.t) => {
let topLine = Editor.getTopVisibleLine(editor);

// Set configured line comment
let lineComment = Internal.lineComment(~maybeLanguageConfig);
let lineComment = Internal.lineComment(~languageConfig);

let indentation = Internal.indentation(~buffer=editorBuffer);

let insertSpaces = indentation.mode == Spaces;

Vim.Context.{
autoIndent,
onOpenAutoIndent,
onTypeAutoIndent,
bufferId,
leftColumn,
topLine,
Expand Down
6 changes: 4 additions & 2 deletions src/reason-libvim/Context.re
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
type t = {
autoClosingPairs: AutoClosingPairs.t,
autoIndent:
onOpenAutoIndent:
(~previousLine: string, ~beforePreviousLine: option(string)) =>
AutoIndent.action,
onTypeAutoIndent: string => AutoIndent.action,
bufferId: int,
width: int,
height: int,
Expand All @@ -16,7 +17,8 @@ type t = {

let current = () => {
autoClosingPairs: AutoClosingPairs.empty,
autoIndent: (~previousLine as _, ~beforePreviousLine as _) => AutoIndent.KeepIndent,
onOpenAutoIndent: (~previousLine as _, ~beforePreviousLine as _) => AutoIndent.KeepIndent,
onTypeAutoIndent: _ => AutoIndent.KeepIndent,
bufferId: Buffer.getCurrent() |> Buffer.getId,
width: Window.getWidth(),
height: Window.getHeight(),
Expand Down
28 changes: 23 additions & 5 deletions src/reason-libvim/Vim.re
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ module Window = Window;
module Yank = Yank;

module GlobalState = {
let autoIndent:
let onOpenAutoIndent:
ref(
option(
(~previousLine: string, ~beforePreviousLine: option(string)) =>
Expand Down Expand Up @@ -175,11 +175,11 @@ let runWith = (~context: Context.t, f) => {
let prevModified = Buffer.isModified(oldBuf);
let prevLineEndings = Buffer.getLineEndings(oldBuf);

GlobalState.autoIndent := Some(context.autoIndent);
GlobalState.onOpenAutoIndent := Some(context.onOpenAutoIndent);

let cursors = f();

GlobalState.autoIndent := None;
GlobalState.onOpenAutoIndent := None;

let newBuf = Buffer.getCurrent();
let newLocation = Cursor.getLocation();
Expand Down Expand Up @@ -381,7 +381,7 @@ let _onAutoIndent = (lnum: int, sourceLine: string) => {
};

let indentAction =
GlobalState.autoIndent^
GlobalState.onOpenAutoIndent^
|> Option.map(fn => fn(~previousLine=beforeLine, ~beforePreviousLine))
|> Option.value(~default=AutoIndent.KeepIndent);

Expand Down Expand Up @@ -454,7 +454,7 @@ let init = () => {
};

let input = (~context=Context.current(), v: string) => {
let {autoClosingPairs, cursors, _}: Context.t = context;
let {autoClosingPairs, cursors, onTypeAutoIndent, _}: Context.t = context;
runWith(
~context,
() => {
Expand All @@ -466,6 +466,9 @@ let input = (~context=Context.current(), v: string) => {
let location = Cursor.getLocation();
let line = Buffer.getLine(Buffer.getCurrent(), location.line);

let beforeLineNumber = location.line;
let beforeIndentAction = context.onTypeAutoIndent(line);

let isBetweenClosingPairs = () => {
AutoClosingPairs.isBetweenClosingPairs(
line,
Expand Down Expand Up @@ -501,6 +504,7 @@ let input = (~context=Context.current(), v: string) => {
if (String.length(precedingWhitespace) > 0) {
Native.vimInput(precedingWhitespace);
};

Native.vimInput("<TAB>");
} else if (AutoClosingPairs.isPassThrough(
v,
Expand All @@ -517,6 +521,20 @@ let input = (~context=Context.current(), v: string) => {
Native.vimInput("<LEFT>");
} else {
Native.vimInput(v);
// If we're still in insert mode, and still on the same line, check the onTypeAutoIndent for adjustments
let afterLineNumber = Cursor.getLocation().line;
let afterLine =
Buffer.getLine(Buffer.getCurrent(), afterLineNumber);
let afterIndentAction = onTypeAutoIndent(afterLine);

if (afterLineNumber == beforeLineNumber
&& afterIndentAction != beforeIndentAction) {
if (afterIndentAction == AutoIndent.IncreaseIndent) {
Native.vimInput("<C-T>");
} else if (afterIndentAction == AutoIndent.DecreaseIndent) {
Native.vimInput("<C-D>");
};
};
};
} else {
Native.vimInput(v);
Expand Down
6 changes: 5 additions & 1 deletion src/reason-libvim/Vim.rei
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,13 @@ module AutoIndent: {
module Context: {
type t = {
autoClosingPairs: AutoClosingPairs.t,
autoIndent:
// Auto-indentation engaged when a new line is entered,
// via `o`, `O`, `<CR>`, etc.
onOpenAutoIndent:
(~previousLine: string, ~beforePreviousLine: option(string)) =>
AutoIndent.action,
// Auto-indentation engaged when the user is typing.
onTypeAutoIndent: string => AutoIndent.action,
bufferId: int,
width: int,
height: int,
Expand Down
Loading