From aabeb57fc04944ddeb1f1c96a7fe931f7d370172 Mon Sep 17 00:00:00 2001 From: Vishesh Handa Date: Fri, 21 Aug 2020 12:18:55 +0200 Subject: [PATCH] InlineTags: Add settings page And support multiple prefixes. This is disabled for now as it hasn't been fully integrated. --- assets/langs/en.yaml | 5 +++++ lib/core/processors/inline_tags.dart | 17 +++++++++++------ lib/features.dart | 1 + lib/screens/settings_screen.dart | 13 +++++++++++++ lib/settings.dart | 23 +++++++++++++++++++++++ test/processors/inline_tags_test.dart | 20 +++++++++++++------- 6 files changed, 66 insertions(+), 13 deletions(-) diff --git a/assets/langs/en.yaml b/assets/langs/en.yaml index c2ffa591..eb564c66 100644 --- a/assets/langs/en.yaml +++ b/assets/langs/en.yaml @@ -90,6 +90,11 @@ settings: remoteSync: auto: Automatic manual: Manual + tags: + title: Tags Settings + subtitle: Configure how inline tags are parsed + enable: Parse Inline Tags + prefixes: Inline Tags Prefixes editors: checklist: diff --git a/lib/core/processors/inline_tags.dart b/lib/core/processors/inline_tags.dart index eb29c89c..7d5c6271 100644 --- a/lib/core/processors/inline_tags.dart +++ b/lib/core/processors/inline_tags.dart @@ -1,16 +1,21 @@ -import 'package:gitjournal/core/note.dart'; +import 'package:meta/meta.dart'; class InlineTagsProcessor { - // FIXME: Make me configurable - final List tagPrefixes = ['#']; + final Set tagPrefixes; - void process(Note note) {} + InlineTagsProcessor({@required this.tagPrefixes}); Set extractTags(String text) { var tags = {}; for (var prefix in tagPrefixes) { - var regexp = RegExp(r'(^|\s)' + prefix + r'([^ ]+)(\s|$)'); + // FIXME: Do not hardcode this + var p = prefix; + if (p == '+') { + p = '\\+'; + } + + var regexp = RegExp(r'(^|\s)' + p + r'([^ ]+)(\s|$)'); var matches = regexp.allMatches(text); for (var match in matches) { var tag = match.group(2); @@ -19,7 +24,7 @@ class InlineTagsProcessor { tag = tag.substring(0, tag.length - 1); } - var all = tag.split('#'); + var all = tag.split(prefix); for (var t in all) { tags.add(t.trim()); } diff --git a/lib/features.dart b/lib/features.dart index bef1e53f..31260527 100644 --- a/lib/features.dart +++ b/lib/features.dart @@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart'; class Features { static bool perFolderConfig = false; + static bool inlineTags = false; static final all = [ Feature.basicSearch, diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index 90fb5756..529dbbb3 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -14,6 +14,7 @@ import 'package:gitjournal/screens/settings_experimental.dart'; import 'package:gitjournal/screens/settings_git_remote.dart'; import 'package:gitjournal/screens/settings_images.dart'; import 'package:gitjournal/screens/settings_note_metadata.dart'; +import 'package:gitjournal/screens/settings_tags.dart'; import 'package:gitjournal/screens/settings_widgets.dart'; import 'package:gitjournal/settings.dart'; import 'package:gitjournal/state_container.dart'; @@ -241,6 +242,18 @@ class SettingsListState extends State { Navigator.of(context).push(route); }, ), + if (Features.inlineTags) + ListTile( + title: Text(tr("settings.tags.title")), + subtitle: Text(tr("settings.tags.subtitle")), + onTap: () { + var route = MaterialPageRoute( + builder: (context) => SettingsTagsScreen(), + settings: const RouteSettings(name: '/settings/tags'), + ); + Navigator.of(context).push(route); + }, + ), ListTile( title: Text(tr('settings.images.title')), subtitle: Text(tr('settings.images.subtitle')), diff --git a/lib/settings.dart b/lib/settings.dart index da561876..bd3dfcc4 100644 --- a/lib/settings.dart +++ b/lib/settings.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:collection/collection.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:uuid/uuid.dart'; @@ -66,6 +67,8 @@ class Settings extends ChangeNotifier { bool zenMode = false; bool saveTitleInH1 = true; + Set inlineTagPrefixes = {'#'}; + void load(SharedPreferences pref) { onBoardingCompleted = pref.getBool("onBoardingCompleted") ?? false; @@ -142,6 +145,8 @@ class Settings extends ChangeNotifier { zenMode = pref.getBool("zenMode") ?? zenMode; saveTitleInH1 = pref.getBool("saveTitleInH1") ?? saveTitleInH1; + inlineTagPrefixes = + pref.getStringList("inlineTagPrefixes")?.toSet() ?? inlineTagPrefixes; } Future save() async { @@ -220,6 +225,8 @@ class Settings extends ChangeNotifier { defaultSet.experimentalMarkdownToolbar); _setBool(pref, "zenMode", zenMode, defaultSet.zenMode); _setBool(pref, "saveTitleInH1", saveTitleInH1, defaultSet.saveTitleInH1); + _setStringSet(pref, "inlineTagPrefixes", inlineTagPrefixes, + defaultSet.inlineTagPrefixes); pref.setInt("settingsVersion", version); @@ -252,6 +259,21 @@ class Settings extends ChangeNotifier { } } + Future _setStringSet( + SharedPreferences pref, + String key, + Set value, + Set defaultValue, + ) async { + final eq = const SetEquality().equals; + + if (eq(value, defaultValue)) { + await pref.remove(key); + } else { + await pref.setStringList(key, value.toList()); + } + } + Map toMap() { return { "onBoardingCompleted": onBoardingCompleted.toString(), @@ -289,6 +311,7 @@ class Settings extends ChangeNotifier { 'experimentalMarkdownToolbar': experimentalMarkdownToolbar.toString(), 'zenMode': zenMode.toString(), 'saveTitleInH1': saveTitleInH1.toString(), + 'inlineTagPrefixes': inlineTagPrefixes.join(' '), }; } diff --git a/test/processors/inline_tags_test.dart b/test/processors/inline_tags_test.dart index fd65eeee..bffa3542 100644 --- a/test/processors/inline_tags_test.dart +++ b/test/processors/inline_tags_test.dart @@ -6,7 +6,7 @@ void main() { test('Should parse simple tags', () { var body = "#hello Hi\nthere how#are you #doing now? #dog"; - var p = InlineTagsProcessor(); + var p = InlineTagsProcessor(tagPrefixes: {'#'}); var tags = p.extractTags(body); expect(tags, {'hello', 'doing', 'dog'}); @@ -15,7 +15,7 @@ void main() { test('Ignore . at the end of a tag', () { var body = "Hi there #tag."; - var p = InlineTagsProcessor(); + var p = InlineTagsProcessor(tagPrefixes: {'#'}); var tags = p.extractTags(body); expect(tags, {'tag'}); @@ -24,7 +24,7 @@ void main() { test('#a#b should be counted as two tags', () { var body = "Hi there #a#b"; - var p = InlineTagsProcessor(); + var p = InlineTagsProcessor(tagPrefixes: {'#'}); var tags = p.extractTags(body); expect(tags, {'a', 'b'}); @@ -33,7 +33,7 @@ void main() { test('Non Ascii tags', () { var body = "Hi #fíre gone"; - var p = InlineTagsProcessor(); + var p = InlineTagsProcessor(tagPrefixes: {'#'}); var tags = p.extractTags(body); expect(tags, {'fíre'}); @@ -42,12 +42,18 @@ void main() { test('Tags with a -', () { var body = "Hi #future-me. How are you?"; - var p = InlineTagsProcessor(); + var p = InlineTagsProcessor(tagPrefixes: {'#'}); var tags = p.extractTags(body); expect(tags, {'future-me'}); }); - // + should work as a prefix - // @ should work as a prefix + test('Multiple Prefixes', () { + var body = "Hi +one+two @foo #doo"; + + var p = InlineTagsProcessor(tagPrefixes: {'#', '+', '@'}); + var tags = p.extractTags(body); + + expect(tags, {'one', 'two', 'foo', 'doo'}); + }); }