3 Commits
Author SHA1 Message Date
Hein a0838e4bdc chore(release): bump version to 0.0.4
Release / Test (push) Successful in 34s
CI / Test (push) Successful in 38s
Release / Windows installer (push) Successful in 58s
CI / Build (push) Successful in 27s
Release / Release (push) Successful in 37s
Release / VSCode Extension (push) Successful in 43s
Release / Debian packages (push) Successful in 59s
Release / RPM package (push) Successful in 1m3s
Release / AUR package (push) Successful in 1m32s
Release / DataGrip Plugin (push) Successful in 3m17s
2026-07-02 14:42:16 +02:00
Hein 44fb77efd6 fix(body): handle CASE depth in body statement formatting
CI / Test (push) Successful in 28s
CI / Build (push) Successful in 25s
2026-07-02 14:40:54 +02:00
Hein 4fab2fe652 feat(ui): add version display action and status bar widget
CI / Test (push) Successful in 29s
CI / Build (push) Successful in 25s
* Implement PgTidyShowVersionAction to show pgtidy version
* Create PgTidyStatusBarWidget for real-time version display
* Update plugin.xml to register new action and widget
2026-07-02 12:58:28 +02:00
6 changed files with 153 additions and 3 deletions
@@ -0,0 +1,42 @@
package com.pgtidy.datagrip
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.Task
import com.intellij.openapi.ui.Messages
class PgTidyShowVersionAction : AnAction() {
override fun actionPerformed(e: AnActionEvent) {
val project = e.project
object : Task.Backgroundable(project, "PgTidy: checking version…", false) {
override fun run(indicator: ProgressIndicator) {
val proc = try {
ProcessBuilder("pgtidy", "version")
.redirectErrorStream(false)
.start()
} catch (ex: Exception) {
ApplicationManager.getApplication().invokeLater {
Messages.showErrorDialog(project, "Cannot start pgtidy: ${ex.message}", "PgTidy")
}
return
}
val output = proc.inputStream.bufferedReader().readText()
val stderr = proc.errorStream.bufferedReader().readText()
val exit = proc.waitFor()
ApplicationManager.getApplication().invokeLater {
if (exit != 0) {
Messages.showErrorDialog(project, stderr.ifBlank { "pgtidy exited with code $exit" }, "PgTidy")
return@invokeLater
}
Messages.showInfoMessage(project, output.trim(), "PgTidy Version")
}
}
}.queue()
}
}
@@ -0,0 +1,72 @@
package com.pgtidy.datagrip
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.wm.StatusBar
import com.intellij.openapi.wm.StatusBarWidget
import com.intellij.openapi.wm.StatusBarWidgetFactory
import com.intellij.util.Consumer
import java.awt.event.MouseEvent
private const val WIDGET_ID = "com.pgtidy.StatusBarWidget"
class PgTidyStatusBarWidget(private val project: Project) : StatusBarWidget, StatusBarWidget.TextPresentation {
private var statusBar: StatusBar? = null
private var text: String = "pgtidy: …"
override fun ID(): String = WIDGET_ID
override fun install(statusBar: StatusBar) {
this.statusBar = statusBar
refresh()
}
override fun dispose() {
statusBar = null
}
override fun getPresentation(): StatusBarWidget.WidgetPresentation = this
override fun getText(): String = text
override fun getAlignment(): Float = java.awt.Component.CENTER_ALIGNMENT
override fun getTooltipText(): String = "PgTidy version — click to refresh"
override fun getClickConsumer(): Consumer<MouseEvent> = Consumer { refresh() }
fun refresh() {
ApplicationManager.getApplication().executeOnPooledThread {
text = try {
val proc = ProcessBuilder("pgtidy", "version")
.redirectErrorStream(true)
.start()
val output = proc.inputStream.bufferedReader().readText().trim()
val exit = proc.waitFor()
if (exit == 0 && output.isNotBlank()) output else "pgtidy: not found"
} catch (ex: Exception) {
"pgtidy: not found"
}
ApplicationManager.getApplication().invokeLater {
statusBar?.updateWidget(WIDGET_ID)
}
}
}
}
class PgTidyStatusBarWidgetFactory : StatusBarWidgetFactory {
override fun getId(): String = WIDGET_ID
override fun getDisplayName(): String = "PgTidy Version"
override fun isAvailable(project: Project): Boolean = true
override fun createWidget(project: Project): StatusBarWidget = PgTidyStatusBarWidget(project)
override fun disposeWidget(widget: StatusBarWidget) {
widget.dispose()
}
override fun canBeEnabledOn(statusBar: StatusBar): Boolean = true
}
@@ -21,8 +21,20 @@
<add-to-group group-id="EditorPopupMenu" anchor="first"/>
<keyboard-shortcut keymap="$default" first-keystroke="ctrl alt shift P"/>
</action>
<action id="com.pgtidy.ShowVersion"
class="com.pgtidy.datagrip.PgTidyShowVersionAction"
text="Show PgTidy Version"
description="Show the installed pgtidy binary version">
<add-to-group group-id="ToolsMenu" anchor="last"/>
</action>
</actions>
<extensions defaultExtensionNs="com.intellij">
<statusBarWidgetFactory id="com.pgtidy.StatusBarWidget"
implementation="com.pgtidy.datagrip.PgTidyStatusBarWidgetFactory"
order="last"/>
</extensions>
<extensions defaultExtensionNs="com.redhat.devtools.lsp4ij">
<server id="com.pgtidy.lsp"
name="PgTidy"
+1 -1
View File
@@ -1,6 +1,6 @@
# Maintainer: Hein (Warky Devs) <hein@warky.dev>
pkgname=pgtidy-bin
pkgver=0.0.3
pkgver=0.0.4
pkgrel=1
pkgdesc="PostgreSQL SQL formatter and linter"
arch=('x86_64' 'aarch64')
+1 -1
View File
@@ -1,5 +1,5 @@
Name: pgtidy
Version: 0.0.3
Version: 0.0.4
Release: 1%{?dist}
Summary: PostgreSQL SQL formatter and linter
+25 -1
View File
@@ -379,6 +379,7 @@ func formatBodyStatements(text string, st config.Style) string {
stmt []bline
parenDepth int
blockDepth int // 0=col-0 (BEGIN/END/EXCEPTION), 1=body, 2=nested…
caseDepth int // depth of open CASE…END expressions (WHEN…THEN is not a block opener)
inException bool
pendingBlanks int
depthInc bool // increment blockDepth after next flush
@@ -529,18 +530,41 @@ func formatBodyStatements(text string, st config.Style) string {
}
if parenDepth == 0 && tok.Kind == lexer.Ident {
lastD0Kw = lowerASCII(tok.Text)
switch lastD0Kw {
case "case":
caseDepth++
case "end":
if caseDepth > 0 {
caseDepth--
}
}
}
}
if parenDepth == 0 && len(stmt) > 0 {
switch lastD0Kw {
case "then", "loop", "begin":
case "then":
// A THEN ending a CASE…WHEN branch is not a PL/pgSQL block
// opener; only one matching END closes the whole CASE, so
// treating each WHEN…THEN as a block open would permanently
// inflate blockDepth.
if caseDepth == 0 {
fw0 := lowerASCII(firstBodyKeyword(stmt[0].text))
if fw0 != "elsif" && fw0 != "elseif" {
depthInc = true
}
flush()
}
case "loop", "begin":
fw0 := lowerASCII(firstBodyKeyword(stmt[0].text))
if fw0 != "elsif" && fw0 != "elseif" {
depthInc = true
}
flush()
case "else", "exception":
if caseDepth > 0 {
break
}
flush()
}
}