diff --git a/lib/widgets/markdown_toolbar.dart b/lib/widgets/markdown_toolbar.dart index 47b8e41e..65c01b85 100644 --- a/lib/widgets/markdown_toolbar.dart +++ b/lib/widgets/markdown_toolbar.dart @@ -23,6 +23,14 @@ class MarkdownToolBar extends StatelessWidget { icon: const Text('B'), onPressed: () => _modifyCurrentWord('**'), ), + IconButton( + icon: const Icon(Icons.navigate_before), + onPressed: _navigateToPrevWord, + ), + IconButton( + icon: const Icon(Icons.navigate_next), + onPressed: _navigateToNextWord, + ), ], ); } @@ -34,6 +42,16 @@ class MarkdownToolBar extends StatelessWidget { void _modifyCurrentWord(String char) { textController.value = modifyCurrentWord(textController.value, char); } + + void _navigateToPrevWord() { + var offset = nextWordPos(textController.value); + textController.selection = TextSelection.collapsed(offset: offset); + } + + void _navigateToNextWord() { + var offset = prevWordPos(textController.value); + textController.selection = TextSelection.collapsed(offset: offset); + } } TextEditingValue modifyCurrentLine( @@ -146,3 +164,28 @@ TextEditingValue modifyCurrentWord( selection: TextSelection.collapsed(offset: wordEndPos), ); } + +// FIXME: This will fail in non space delimited languages +int nextWordPos(TextEditingValue textEditingValue) { + var cursorPos = textEditingValue.selection.baseOffset; + var text = textEditingValue.text; + + var nextSpacePos = text.indexOf(RegExp('\s'), cursorPos); + if (nextSpacePos == -1) { + return text.length; + } + + return nextSpacePos; +} + +int prevWordPos(TextEditingValue textEditingValue) { + var cursorPos = textEditingValue.selection.baseOffset; + var text = textEditingValue.text; + + var lastSpacePos = text.lastIndexOf(RegExp('\s'), cursorPos); + if (lastSpacePos == -1) { + return 0; + } + + return lastSpacePos; +} diff --git a/test/markdown_toolbar_test.dart b/test/markdown_toolbar_test.dart index a3f99b98..6a74b70e 100644 --- a/test/markdown_toolbar_test.dart +++ b/test/markdown_toolbar_test.dart @@ -166,4 +166,40 @@ void main() { char: '**', ); }); + + // + // Navigation + // + test('Navigation with only 1 word', () { + var val = const TextEditingValue( + text: 'Hello', + selection: TextSelection.collapsed(offset: 3), + ); + + expect(nextWordPos(val), 5); + + val = const TextEditingValue( + text: 'Hello', + selection: TextSelection.collapsed(offset: 5), + ); + + expect(nextWordPos(val), 5); + + val = const TextEditingValue( + text: 'Hello', + selection: TextSelection.collapsed(offset: 3), + ); + + expect(prevWordPos(val), 0); + + val = const TextEditingValue( + text: 'Hello', + selection: TextSelection.collapsed(offset: 5), + ); + + expect(prevWordPos(val), 0); + }); + + // Test for navigating between punctuations + // Test for navigating between newlines }