diff --git a/src/main/scala/gitbucket/core/plugin/CompletionProposalProvider.scala b/src/main/scala/gitbucket/core/plugin/CompletionProposalProvider.scala
new file mode 100644
index 0000000..a92e753
--- /dev/null
+++ b/src/main/scala/gitbucket/core/plugin/CompletionProposalProvider.scala
@@ -0,0 +1,33 @@
+package gitbucket.core.plugin
+
+import gitbucket.core.controller.Context
+import gitbucket.core.util.EmojiUtil
+
+trait CompletionProposalProvider {
+
+ val id: String
+ val prefix: String
+ val suffix: String = " "
+ val values: Seq[String]
+
+ def template(implicit context: Context): String = "value"
+ def additionalScript(implicit context: Context): String = ""
+}
+
+class EmojiCompletionProposalProvider extends CompletionProposalProvider {
+ override val id: String = "emoji"
+ override val values: Seq[String] = EmojiUtil.emojis.toSeq
+ override val prefix: String = ":"
+ override val suffix: String = ": "
+ override def template(implicit context: Context): String =
+ s"""'' + value"""
+}
+
+class UserCompletionProposalProvider extends CompletionProposalProvider {
+ override val id: String = "user"
+ override val values: Seq[String] = Nil
+ override val prefix: String = "@"
+ override def template(implicit context: Context): String = "'@' + value"
+ override def additionalScript(implicit context: Context): String =
+ s"""$$.get('${context.path}/_user/proposals', { query: '' }, function (data) { user = data.options; });"""
+}
\ No newline at end of file
diff --git a/src/main/scala/gitbucket/core/plugin/Plugin.scala b/src/main/scala/gitbucket/core/plugin/Plugin.scala
index 62b2ccb..3478d5b 100644
--- a/src/main/scala/gitbucket/core/plugin/Plugin.scala
+++ b/src/main/scala/gitbucket/core/plugin/Plugin.scala
@@ -170,6 +170,16 @@
def textDecorators(registry: PluginRegistry, context: ServletContext, settings: SystemSettings): Seq[TextDecorator] = Nil
/**
+ * Override to add completion proposal provider.
+ */
+ val completionProposalProvider: Seq[CompletionProposalProvider] = Nil
+
+ /**
+ * Override to add completion proposal provider.
+ */
+ def completionProposalProvider(registry: PluginRegistry, context: ServletContext, settings: SystemSettings): Seq[CompletionProposalProvider] = Nil
+
+ /**
* This method is invoked in initialization of plugin system.
* Register plugin functionality to PluginRegistry.
*/
@@ -219,6 +229,9 @@
(textDecorators ++ textDecorators(registry, context, settings)).foreach { textDecorator =>
registry.addTextDecorator(textDecorator)
}
+ (completionProposalProvider ++ completionProposalProvider(registry, context, settings)).foreach { completionProposalProvider =>
+ registry.addCompletionProposalProvider(completionProposalProvider)
+ }
}
/**
diff --git a/src/main/scala/gitbucket/core/plugin/PluginRegistory.scala b/src/main/scala/gitbucket/core/plugin/PluginRegistory.scala
index e3a7f2a..c867d35 100644
--- a/src/main/scala/gitbucket/core/plugin/PluginRegistory.scala
+++ b/src/main/scala/gitbucket/core/plugin/PluginRegistory.scala
@@ -43,9 +43,13 @@
private val dashboardTabs = new ListBuffer[(Context) => Option[Link]]
private val assetsMappings = new ListBuffer[(String, String, ClassLoader)]
private val textDecorators = new ListBuffer[TextDecorator]
+ // TODO
textDecorators += new TextDecorator {
override def decorate(text: String)(implicit context: Context): String = EmojiUtil.convertEmojis(text)
}
+ private val completionProposalProviders = new ListBuffer[CompletionProposalProvider]
+ completionProposalProviders += new EmojiCompletionProposalProvider()
+ completionProposalProviders += new UserCompletionProposalProvider()
def addPlugin(pluginInfo: PluginInfo): Unit = plugins += pluginInfo
@@ -136,6 +140,10 @@
def addTextDecorator(textDecorator: TextDecorator): Unit = textDecorators += textDecorator
def getTextDecorators: Seq[TextDecorator] = textDecorators.toSeq
+
+ def addCompletionProposalProvider(completionProposalProvider: CompletionProposalProvider): Unit = completionProposalProviders += completionProposalProvider
+
+ def getCompletionProposalProviders: Seq[CompletionProposalProvider] = completionProposalProviders.toSeq
}
/**
diff --git a/src/main/scala/gitbucket/core/view/helpers.scala b/src/main/scala/gitbucket/core/view/helpers.scala
index 34c01f1..91317e4 100644
--- a/src/main/scala/gitbucket/core/view/helpers.scala
+++ b/src/main/scala/gitbucket/core/view/helpers.scala
@@ -315,6 +315,14 @@
case CommitState.FAILURE => "Failed"
}
+ /**
+ * Render a given object as the JSON string.
+ */
+ def json(obj: AnyRef): String = {
+ implicit val formats = org.json4s.DefaultFormats
+ org.json4s.jackson.Serialization.write(obj)
+ }
+
// This pattern comes from: http://stackoverflow.com/a/4390768/1771641 (extract-url-from-string)
private[this] val detectAndRenderLinksRegex = """(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,13}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))""".r
diff --git a/src/main/twirl/gitbucket/core/helper/attached.scala.html b/src/main/twirl/gitbucket/core/helper/attached.scala.html
index aaed7c4..d1d5557 100644
--- a/src/main/twirl/gitbucket/core/helper/attached.scala.html
+++ b/src/main/twirl/gitbucket/core/helper/attached.scala.html
@@ -1,5 +1,6 @@
@(owner: String, repository: String, completion: Seq[String], generateScript: Boolean = true)(textarea: Html)(implicit context: gitbucket.core.controller.Context)
@import gitbucket.core.util.{FileUtil, EmojiUtil}
+@import gitbucket.core.view.helpers