@@ -50,6 +50,7 @@ import javax.swing.JComponent
50
50
import javax.swing.JLabel
51
51
import javax.swing.JPanel
52
52
import javax.swing.SwingConstants
53
+ import javax.swing.border.LineBorder
53
54
54
55
class TerminalSketchProvider : LanguageSketchProvider {
55
56
override fun isSupported (lang : String ): Boolean = lang == " bash" || lang == " shell"
@@ -83,11 +84,15 @@ class TerminalLangSketch(val project: Project, var content: String) : ExtensionL
83
84
val resultSketch = CodeHighlightSketch (project, " " , CodeFence .findLanguage(" bash" )).apply {
84
85
border = JBUI .Borders .empty()
85
86
}
87
+
86
88
val resultPanel = JPanel (BorderLayout ()).apply {
89
+ border = JBUI .Borders .empty()
87
90
add(resultSketch.getComponent(), BorderLayout .CENTER )
88
91
}
89
92
90
- val collapsibleCodePanel = CollapsiblePanel (" Shell Code" , codePanel, initiallyCollapsed = true )
93
+ private val successColor = JBColor (Color (233 , 255 , 233 ), Color (0 , 77 , 0 ))
94
+ private val errorColor = JBColor (Color (255 , 233 , 233 ), Color (77 , 0 , 0 ))
95
+ private val normalColor = resultPanel.background
91
96
92
97
val collapsibleResultPanel = CollapsiblePanel (" Execution Results" , resultPanel, initiallyCollapsed = true )
93
98
@@ -101,7 +106,8 @@ class TerminalLangSketch(val project: Project, var content: String) : ExtensionL
101
106
}
102
107
103
108
private lateinit var executeAction: TerminalExecuteAction
104
- private lateinit var resizableTerminalPanel: ResizableTerminalPanel
109
+ private var resizableTerminalPanel: ResizableTerminalPanel
110
+ private var isCodePanelVisible = false
105
111
106
112
init {
107
113
val projectDir = project.guessProjectDir()?.path
@@ -119,22 +125,65 @@ class TerminalLangSketch(val project: Project, var content: String) : ExtensionL
119
125
mainPanel = object : JPanel (VerticalLayout (JBUI .scale(0 ))) {
120
126
init {
121
127
add(toolbarWrapper)
122
- add(collapsibleCodePanel)
123
128
add(collapsibleResultPanel)
124
129
add(resizableTerminalPanel)
125
130
}
126
131
}
127
132
128
133
mainPanel!! .border = JBUI .Borders .compound(
129
134
JBUI .Borders .customLine(UIUtil .getBoundsColor(), 1 ),
130
- JBUI .Borders .empty(0 , 4 )
135
+ JBUI .Borders .empty()
131
136
)
132
137
terminalWidget!! .addMessageFilter(FrontendWebViewServerFilter (project, mainPanel!! ))
133
138
}
139
+
140
+ private fun setResultStatus (success : Boolean , errorMessage : String? = null) {
141
+ ApplicationManager .getApplication().invokeLater {
142
+ when {
143
+ success -> {
144
+ resultPanel.background = successColor
145
+ resultPanel.border = LineBorder (JBColor (Color (0 , 128 , 0 ), Color (0 , 100 , 0 )), 1 )
146
+ collapsibleResultPanel.setTitle(" ✅ Execution Successful" )
147
+ }
148
+ errorMessage != null -> {
149
+ resultPanel.background = errorColor
150
+ resultPanel.border = LineBorder (JBColor (Color (128 , 0 , 0 ), Color (100 , 0 , 0 )), 1 )
151
+ collapsibleResultPanel.setTitle(" ❌ Execution Failed" )
152
+ }
153
+ else -> {
154
+ resultPanel.background = normalColor
155
+ resultPanel.border = null
156
+ collapsibleResultPanel.setTitle(" Execution Results" )
157
+ }
158
+ }
159
+ resultPanel.repaint()
160
+ }
161
+ }
162
+
163
+ private fun toggleCodePanel () {
164
+ if (isCodePanelVisible) {
165
+ mainPanel!! .remove(codePanel)
166
+ isCodePanelVisible = false
167
+ } else {
168
+ // Add code panel at index 1 (after toolbar, before result panel)
169
+ mainPanel!! .add(codePanel, 1 )
170
+ isCodePanelVisible = true
171
+ }
172
+
173
+ mainPanel!! .revalidate()
174
+ mainPanel!! .repaint()
175
+ }
134
176
135
177
fun createConsoleActions (): List <AnAction > {
136
178
executeAction = TerminalExecuteAction ()
137
179
180
+ val showCodeAction = object :
181
+ AnAction (" Show/Hide Code" , " Show or hide the shell code" , AllIcons .Actions .ShowCode ) {
182
+ override fun actionPerformed (e : AnActionEvent ) {
183
+ toggleCodePanel()
184
+ }
185
+ }
186
+
138
187
val copyAction = object :
139
188
AnAction (" Copy" , AutoDevBundle .message(" sketch.terminal.copy.text" ), AllIcons .Actions .Copy ) {
140
189
override fun actionPerformed (e : AnActionEvent ) {
@@ -170,7 +219,7 @@ class TerminalLangSketch(val project: Project, var content: String) : ExtensionL
170
219
}
171
220
}
172
221
173
- return listOf (executeAction, copyAction, sendAction, popupAction)
222
+ return listOf (executeAction, showCodeAction, copyAction, sendAction, popupAction)
174
223
}
175
224
176
225
private fun executePopup (terminalWidget : JBTerminalWidget ? , project : Project ): MouseAdapter =
@@ -232,7 +281,7 @@ class TerminalLangSketch(val project: Project, var content: String) : ExtensionL
232
281
" ⚠️ WARNING: $reason \n The command was not auto-executed for safety reasons.\n Please review and run manually if you're sure." ,
233
282
true
234
283
)
235
- collapsibleResultPanel.setTitle( " Safety Warning " )
284
+ setResultStatus( false , reason )
236
285
collapsibleResultPanel.expand()
237
286
}
238
287
return
@@ -286,23 +335,28 @@ class TerminalLangSketch(val project: Project, var content: String) : ExtensionL
286
335
287
336
resultSketch.updateViewText(" " , true )
288
337
stdWriter.setExecuting(true )
338
+ // Reset result panel appearance
339
+ setResultStatus(false )
289
340
290
341
AutoDevCoroutineScope .scope(project).launch {
291
342
val executor = ProcessExecutor (project)
292
343
try {
293
344
val dispatcher = PooledThreadExecutor .INSTANCE .asCoroutineDispatcher()
294
- executor.exec(getViewText(), stdWriter, stdWriter, dispatcher)
345
+ val exitCode = executor.exec(getViewText(), stdWriter, stdWriter, dispatcher)
295
346
ApplicationManager .getApplication().invokeLater {
296
347
stdWriter.setExecuting(false )
297
348
if (collapsibleResultPanel.isCollapsed()) {
298
349
collapsibleResultPanel.expand()
299
350
}
351
+ // Set success/failure based on exit code
352
+ val success = exitCode == 0
353
+ setResultStatus(success, if (! success) " Process exited with code $exitCode " else null )
300
354
}
301
355
} catch (ex: Exception ) {
302
356
ApplicationManager .getApplication().invokeLater {
303
357
stdWriter.setExecuting(false )
304
358
resultSketch.updateViewText(" ${stdWriter.getContent()} \n Error: ${ex.message} " , true )
305
- collapsibleResultPanel.setTitle( " Execution Results (Error) " )
359
+ setResultStatus( false , ex.message )
306
360
}
307
361
}
308
362
}
0 commit comments