mirror of
https://github.com/GitJournal/GitJournal.git
synced 2025-07-15 07:56:11 +08:00
Refactor Auto bullet list in Editor
The earlier code base was a bit fragile, I prefer having this unit-tested as the logic is a bit tricky, and I still don't support all the use-cases.
This commit is contained in:
40
lib/editors/heuristics.dart
Normal file
40
lib/editors/heuristics.dart
Normal file
@ -0,0 +1,40 @@
|
||||
class EditorHeuristicResult {
|
||||
String text;
|
||||
int cursorPos;
|
||||
|
||||
EditorHeuristicResult(this.text, this.cursorPos);
|
||||
}
|
||||
|
||||
EditorHeuristicResult autoAddBulletList(
|
||||
String oldText, String curText, int cursorPos) {
|
||||
// We only want to do this on inserts
|
||||
if (curText.length <= oldText.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Only when getting a new line
|
||||
if (curText[cursorPos - 1] != '\n') {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Only add the bullets at the end of the document
|
||||
// FIXME: We should do this anywhere
|
||||
if (curText.length != cursorPos) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var prevLineStart = curText.lastIndexOf('\n', cursorPos - 2);
|
||||
prevLineStart = prevLineStart == -1 ? 0 : prevLineStart + 1;
|
||||
var prevLine = curText.substring(prevLineStart, cursorPos - 1);
|
||||
|
||||
var pattern = RegExp(r'^(\s*)([*\-])');
|
||||
var match = pattern.firstMatch(prevLine);
|
||||
if (match == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var indent = match.group(1) ?? "";
|
||||
var text = curText.substring(0, cursorPos) + indent + match.group(2) + ' ';
|
||||
|
||||
return EditorHeuristicResult(text, text.length);
|
||||
}
|
@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:gitjournal/core/note.dart';
|
||||
import 'package:gitjournal/editors/common.dart';
|
||||
import 'package:gitjournal/editors/heuristics.dart';
|
||||
import 'package:gitjournal/editors/note_title_editor.dart';
|
||||
import 'package:gitjournal/settings.dart';
|
||||
import 'package:gitjournal/widgets/editor_scroll_view.dart';
|
||||
@ -54,7 +55,7 @@ class MarkdownEditorState extends State<MarkdownEditor> implements EditorState {
|
||||
TextEditingController _textController = TextEditingController();
|
||||
TextEditingController _titleTextController = TextEditingController();
|
||||
|
||||
int _textLength;
|
||||
String _oldText;
|
||||
|
||||
bool editingMode = true;
|
||||
bool _noteModified;
|
||||
@ -62,7 +63,7 @@ class MarkdownEditorState extends State<MarkdownEditor> implements EditorState {
|
||||
MarkdownEditorState(this.note) {
|
||||
_textController = TextEditingController(text: note.body);
|
||||
_titleTextController = TextEditingController(text: note.title);
|
||||
_textLength = note.body.length;
|
||||
_oldText = note.body;
|
||||
|
||||
editingMode = Settings.instance.markdownDefaultView ==
|
||||
SettingsMarkdownDefaultView.Edit;
|
||||
@ -153,7 +154,7 @@ class MarkdownEditorState extends State<MarkdownEditor> implements EditorState {
|
||||
|
||||
void _noteTextChanged() {
|
||||
try {
|
||||
_insertExtraCharactersOnEnter();
|
||||
_applyHeuristics();
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
@ -167,38 +168,23 @@ class MarkdownEditorState extends State<MarkdownEditor> implements EditorState {
|
||||
}
|
||||
}
|
||||
|
||||
void _insertExtraCharactersOnEnter() {
|
||||
var text = _textController.text;
|
||||
if (text.length <= _textLength) {
|
||||
_textLength = text.length;
|
||||
return;
|
||||
}
|
||||
_textLength = text.length;
|
||||
|
||||
void _applyHeuristics() {
|
||||
var selection = _textController.selection;
|
||||
if (selection.baseOffset != selection.extentOffset) {
|
||||
_oldText = _textController.text;
|
||||
return;
|
||||
}
|
||||
|
||||
var cursorPos = selection.baseOffset;
|
||||
if (cursorPos != _textLength || text[cursorPos - 1] != '\n') {
|
||||
return;
|
||||
}
|
||||
var prevLineStart = text.lastIndexOf('\n', cursorPos - 2);
|
||||
prevLineStart = prevLineStart == -1 ? 0 : prevLineStart + 1;
|
||||
var prevLine = text.substring(prevLineStart, cursorPos - 1);
|
||||
var r =
|
||||
autoAddBulletList(_oldText, _textController.text, selection.baseOffset);
|
||||
_oldText = _textController.text;
|
||||
|
||||
var pattern = RegExp(r'^(\s*)([*\-])');
|
||||
var match = pattern.firstMatch(prevLine);
|
||||
if (match == null) {
|
||||
if (r == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var indent = match.group(1) ?? "";
|
||||
_textController.text =
|
||||
text.substring(0, cursorPos) + indent + match.group(2) + ' ';
|
||||
_textLength = _textController.text.length;
|
||||
_textController.selection = TextSelection.collapsed(offset: _textLength);
|
||||
_textController.text = r.text;
|
||||
_textController.selection = TextSelection.collapsed(offset: r.cursorPos);
|
||||
}
|
||||
|
||||
@override
|
||||
|
23
test/editor_heuristics_test.dart
Normal file
23
test/editor_heuristics_test.dart
Normal file
@ -0,0 +1,23 @@
|
||||
import 'package:test/test.dart';
|
||||
import 'package:gitjournal/editors/heuristics.dart';
|
||||
|
||||
void main() {
|
||||
group('Editor Heuristic Tests', () {
|
||||
test('Does not modify test on newline', () {
|
||||
var origText = "Hello";
|
||||
var newText = "Hello\n";
|
||||
|
||||
var result = autoAddBulletList(origText, newText, newText.length);
|
||||
expect(result, null);
|
||||
});
|
||||
|
||||
test('Adds a bullet item', () {
|
||||
var origText = "Hello\n* One";
|
||||
var newText = "Hello\n* One\n";
|
||||
|
||||
var result = autoAddBulletList(origText, newText, newText.length);
|
||||
expect(result.text, "Hello\n* One\n* ");
|
||||
expect(result.cursorPos, result.text.length);
|
||||
});
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user