Skip to content

Commit f281980

Browse files
authored
✨ Gitmoji column (#60)
1 parent 0f42ff1 commit f281980

File tree

8 files changed

+157
-72
lines changed

8 files changed

+157
-72
lines changed

src/main/kotlin/com/github/patou/gitmoji/GitCommitAction.kt

Lines changed: 7 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
package com.github.patou.gitmoji
22

3-
import com.github.patou.gitmoji.Gitmojis.Companion.insertAt
4-
import com.google.gson.Gson
53
import com.intellij.ide.TextCopyProvider
64
import com.intellij.ide.util.PropertiesComponent
5+
import com.intellij.openapi.actionSystem.ActionUpdateThread
76
import com.intellij.openapi.actionSystem.AnAction
87
import com.intellij.openapi.actionSystem.AnActionEvent
98
import com.intellij.openapi.actionSystem.PlatformDataKeys
@@ -30,19 +29,14 @@ import com.intellij.util.ObjectUtils.sentinel
3029
import com.intellij.util.containers.nullize
3130
import com.intellij.util.ui.JBUI.scale
3231
import com.intellij.vcs.commit.message.CommitMessageInspectionProfile.getSubjectRightMargin
33-
import okhttp3.*
34-
import okhttp3.Request.Builder
3532
import java.awt.Point
36-
import java.io.IOException
3733
import javax.swing.JList
3834
import javax.swing.ListSelectionModel
3935

4036
class GitCommitAction : AnAction() {
41-
private val gitmojis = ArrayList<GitmojiData>()
4237

4338
init {
4439
isEnabledInModalContext = true
45-
loadGitmojiFromHTTP()
4640
}
4741

4842
private val regexPattern = ":[a-z0-9_]+:"
@@ -56,12 +50,13 @@ class GitCommitAction : AnAction() {
5650
val commitMessage = getCommitMessage(actionEvent)
5751
when {
5852
commitMessage != null && project != null -> {
59-
createPopup(project, commitMessage, gitmojis)
53+
createPopup(project, commitMessage, Gitmojis.gitmojis)
6054
.showInBestPositionFor(actionEvent.dataContext)
6155
}
6256
}
6357
}
6458

59+
@Suppress("MissingActionUpdateThread")
6560
private fun createPopup(
6661
project: Project,
6762
commitMessage: CommitMessage,
@@ -73,7 +68,7 @@ class GitCommitAction : AnAction() {
7368
val previewCommandGroup = sentinel("Preview Commit Message")
7469
val projectInstance = PropertiesComponent.getInstance(project)
7570
val displayEmoji =
76-
projectInstance.getValue(CONFIG_DISPLAY_ICON, Gitmojis.defaultDisplayType()) == "emoji"
71+
projectInstance.getValue(CONFIG_DISPLAY_ICON, defaultDisplayType()) == "emoji"
7772
val currentCommitMessage = commitMessage.editorField.text
7873
val currentOffset = commitMessage.editorField.caretModel.offset
7974

@@ -172,7 +167,7 @@ class GitCommitAction : AnAction() {
172167
var replaced = false
173168
if (!insertInCarretPosition) {
174169
if (useUnicode) {
175-
for (moji in gitmojis) {
170+
for (moji in Gitmojis.gitmojis) {
176171
if (message.contains("${moji.emoji}$textAfterUnicode")) {
177172
message = message.replaceFirst(
178173
"${moji.emoji}$textAfterUnicode",
@@ -224,43 +219,8 @@ class GitCommitAction : AnAction() {
224219
private fun getCommitMessage(e: AnActionEvent) =
225220
e.getData(VcsDataKeys.COMMIT_MESSAGE_CONTROL) as? CommitMessage
226221

227-
private fun loadGitmojiFromHTTP() {
228-
val client = OkHttpClient().newBuilder().addInterceptor(SafeGuardInterceptor()).build()
229-
val request: Request = Builder()
230-
.url("https://gitmoji.dev/api/gitmojis")
231-
.build()
232-
client.newCall(request).enqueue(object : Callback {
233-
override fun onFailure(call: Call, e: IOException) {
234-
loadDefaultGitmoji()
235-
}
236-
237-
override fun onResponse(call: Call, response: Response) {
238-
response.use {
239-
if (!response.isSuccessful) loadDefaultGitmoji()
240-
else {
241-
loadGitmoji(response.body!!.string())
242-
}
243-
}
244-
}
245-
})
246-
}
247-
248-
private fun loadDefaultGitmoji() {
249-
javaClass.getResourceAsStream("/gitmojis.json").use { inputStream ->
250-
if (inputStream != null) {
251-
val text = inputStream.bufferedReader().readText()
252-
loadGitmoji(text)
253-
}
254-
}
255-
}
256-
257-
private fun loadGitmoji(text: String) {
258-
Gson().fromJson(text, Gitmojis::class.java).also {
259-
it.gitmojis.forEach { gitmoji ->
260-
gitmojis.add(GitmojiData(gitmoji.code, gitmoji.emoji, gitmoji.description, gitmoji.name))
261-
}
262-
}
263-
GitmojiLocale.loadTranslations()
222+
override fun getActionUpdateThread(): ActionUpdateThread {
223+
return ActionUpdateThread.BGT
264224
}
265225

266226
}

src/main/kotlin/com/github/patou/gitmoji/GitMojiConfig.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class GitMojiConfig(private val project: Project) : SearchableConfigurable {
9191
val propertiesComponent = PropertiesComponent.getInstance(project)
9292
val instance = PropertiesComponent.getInstance()
9393

94-
displayEmojiConfig = propertiesComponent.getValue(CONFIG_DISPLAY_ICON, Gitmojis.defaultDisplayType())
94+
displayEmojiConfig = propertiesComponent.getValue(CONFIG_DISPLAY_ICON, defaultDisplayType())
9595
useUnicodeConfig = propertiesComponent.getBoolean(CONFIG_USE_UNICODE, false)
9696
insertInCursorPositionConfig = propertiesComponent.getBoolean(CONFIG_INSERT_IN_CURSOR_POSITION, false)
9797
includeGitMojiDescriptionConfig = propertiesComponent.getBoolean(CONFIG_INCLUDE_GITMOJI_DESCRIPTION, false)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.github.patou.gitmoji
2+
3+
import com.intellij.vcs.log.ui.table.VcsLogGraphTable
4+
import com.intellij.vcs.log.ui.table.VcsLogIconCellRenderer
5+
6+
class GitmojiCellRenderer : VcsLogIconCellRenderer() {
7+
override fun customize(
8+
table: VcsLogGraphTable,
9+
value: Any?,
10+
selected: Boolean,
11+
hasFocus: Boolean,
12+
row: Int,
13+
column: Int
14+
) {
15+
if (value == null || value !is GitmojiData) {
16+
return
17+
}
18+
if (value.name == "anguished") {
19+
append("-")
20+
return
21+
}
22+
icon = value.getIcon()
23+
toolTipText = value.localeDescription
24+
}
25+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.github.patou.gitmoji
2+
3+
import com.intellij.ide.util.PropertiesComponent
4+
import com.intellij.openapi.project.ProjectManager
5+
import com.intellij.vcs.log.ui.table.GraphTableModel
6+
import com.intellij.vcs.log.ui.table.VcsLogGraphTable
7+
import com.intellij.vcs.log.ui.table.column.VcsLogCustomColumn
8+
import javax.swing.table.TableCellRenderer
9+
10+
11+
@Suppress("UnstableApiUsage")
12+
class GitmojiCustomColumn : VcsLogCustomColumn<GitmojiData> {
13+
override val id: String
14+
get() = "gitmoji"
15+
override val isDynamic: Boolean
16+
get() = true
17+
override val localizedName: String
18+
get() = "Gitmoji"
19+
override val isResizable: Boolean
20+
get() = false
21+
22+
override fun createTableCellRenderer(table: VcsLogGraphTable): TableCellRenderer {
23+
return GitmojiCellRenderer()
24+
}
25+
26+
override fun isEnabledByDefault(): Boolean {
27+
val projectInstance = PropertiesComponent.getInstance(ProjectManager.getInstance().defaultProject)
28+
val useUnicode = projectInstance.getBoolean(CONFIG_USE_UNICODE, false)
29+
return useUnicode
30+
}
31+
32+
override fun getStubValue(model: GraphTableModel): GitmojiData {
33+
return GitmojiData("anguished", "😧", "anguished", "anguished")
34+
}
35+
36+
override fun getValue(model: GraphTableModel, row: Int): GitmojiData? {
37+
model.getCommitMetadata(row).let {
38+
for (moji in Gitmojis.gitmojis) {
39+
if (it.subject.contains(moji.emoji) || it.subject.contains(moji.code)) {
40+
return moji
41+
}
42+
}
43+
}
44+
return null
45+
}
46+
47+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.github.patou.gitmoji
2+
3+
import com.intellij.openapi.util.SystemInfo
4+
5+
fun defaultDisplayType(): String {
6+
return if (SystemInfo.isWindows) "icon" else "emoji"
7+
}
8+
9+
fun insertAt(target: String, position: Int, insert: String): String {
10+
val targetLen = target.length
11+
require(!(position < 0 || position > targetLen)) { "position=$position" }
12+
if (insert.isEmpty()) {
13+
return target
14+
}
15+
if (position == 0) {
16+
return insert + target
17+
} else if (position == targetLen) {
18+
return target + insert
19+
}
20+
val insertLen = insert.length
21+
val buffer = CharArray(targetLen + insertLen)
22+
target.toCharArray(buffer, 0, 0, position)
23+
insert.toCharArray(buffer, position, 0, insertLen)
24+
target.toCharArray(buffer, position + insertLen, position, targetLen)
25+
return String(buffer)
26+
}
Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,54 @@
11
package com.github.patou.gitmoji
22

3-
import com.intellij.openapi.util.SystemInfo
3+
import com.google.gson.Gson
4+
import okhttp3.*
5+
import okhttp3.Request.Builder
6+
import java.io.IOException
47

5-
class Gitmojis(val gitmojis: List<Gitmoji>) {
6-
class Gitmoji(val emoji: String, val code: String, val description: String, val name: String)
8+
object Gitmojis {
9+
val gitmojis = ArrayList<GitmojiData>()
710

8-
companion object {
9-
fun defaultDisplayType(): String {
10-
return if (SystemInfo.isWindows) "icon" else "emoji"
11-
}
11+
init {
12+
loadGitmojiFromHTTP()
13+
}
14+
15+
private fun loadGitmojiFromHTTP() {
16+
val client = OkHttpClient().newBuilder().addInterceptor(SafeGuardInterceptor()).build()
17+
val request: Request = Builder()
18+
.url("https://gitmoji.dev/api/gitmojis")
19+
.build()
20+
client.newCall(request).enqueue(object : Callback {
21+
override fun onFailure(call: Call, e: IOException) {
22+
loadDefaultGitmoji()
23+
}
1224

13-
fun insertAt(target: String, position: Int, insert: String): String {
14-
val targetLen = target.length
15-
require(!(position < 0 || position > targetLen)) { "position=$position" }
16-
if (insert.isEmpty()) {
17-
return target
25+
override fun onResponse(call: Call, response: Response) {
26+
response.use {
27+
if (!response.isSuccessful) loadDefaultGitmoji()
28+
else {
29+
loadGitmoji(response.body!!.string())
30+
}
31+
}
1832
}
19-
if (position == 0) {
20-
return insert + target
21-
} else if (position == targetLen) {
22-
return target + insert
33+
})
34+
}
35+
36+
private fun loadDefaultGitmoji() {
37+
javaClass.getResourceAsStream("/gitmojis.json").use { inputStream ->
38+
if (inputStream != null) {
39+
val text = inputStream.bufferedReader().readText()
40+
loadGitmoji(text)
2341
}
24-
val insertLen = insert.length
25-
val buffer = CharArray(targetLen + insertLen)
26-
target.toCharArray(buffer, 0, 0, position)
27-
insert.toCharArray(buffer, position, 0, insertLen)
28-
target.toCharArray(buffer, position + insertLen, position, targetLen)
29-
return String(buffer)
3042
}
3143
}
32-
}
44+
45+
private fun loadGitmoji(text: String) {
46+
Gson().fromJson(text, JsonGitmojis::class.java).also {
47+
it.gitmojis.forEach { gitmoji ->
48+
gitmojis.add(GitmojiData(gitmoji.code, gitmoji.emoji, gitmoji.description, gitmoji.name))
49+
}
50+
}
51+
GitmojiLocale.loadTranslations()
52+
}
53+
54+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.github.patou.gitmoji
2+
3+
class JsonGitmojis(val gitmojis: List<JsonGitmoji>) {
4+
class JsonGitmoji(val emoji: String, val code: String, val description: String, val name: String)
5+
}

src/main/resources/META-INF/plugin.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@
4141
</actions>
4242

4343
<extensions defaultExtensionNs="com.intellij">
44-
4544
<projectConfigurable instance="com.github.patou.gitmoji.GitMojiConfig" groupId="other" key="projectName" bundle="messages.GitmojiBundle"
4645
id="com.github.patou.gitmoji.config"/>
46+
<vcsLogCustomColumn implementation="com.github.patou.gitmoji.GitmojiCustomColumn" />
4747
</extensions>
4848
</idea-plugin>

0 commit comments

Comments
 (0)