1-
21package com.github.continuedev.continueintellijextension.`continue`
32
43import com.github.continuedev.continueintellijextension.*
@@ -27,12 +26,14 @@ import com.intellij.openapi.fileEditor.FileDocumentManager
2726import com.intellij.openapi.fileEditor.FileEditorManager
2827import com.intellij.openapi.project.Project
2928import com.intellij.openapi.project.guessProjectDir
30- import com.intellij.openapi.util.IconLoader
3129import com.intellij.openapi.vfs.LocalFileSystem
3230import com.intellij.openapi.vfs.VirtualFileManager
31+ import com.intellij.openapi.wm.ToolWindowManager
3332import com.intellij.psi.PsiDocumentManager
3433import com.intellij.testFramework.LightVirtualFile
3534import kotlinx.coroutines.*
35+ import org.jetbrains.plugins.terminal.ShellTerminalWidget
36+ import org.jetbrains.plugins.terminal.TerminalView
3637import java.awt.Toolkit
3738import java.awt.datatransfer.DataFlavor
3839import java.io.BufferedReader
@@ -54,7 +55,7 @@ class IntelliJIDE(
5455 init {
5556 try {
5657 val os = getOS()
57-
58+
5859 if (os == OS .LINUX || os == OS .MAC ) {
5960 val file = File (ripgrep)
6061 if (! file.canExecute()) {
@@ -135,7 +136,33 @@ class IntelliJIDE(
135136 }
136137
137138 override suspend fun getTerminalContents (): String {
138- return " "
139+ return withContext(Dispatchers .EDT ) {
140+ try {
141+ val toolWindow = ToolWindowManager .getInstance(project).getToolWindow(" Terminal" )
142+
143+ val terminalView = TerminalView .getInstance(project)
144+ // Find the first terminal widget selected, whatever its state, running command or not.
145+ val widget = terminalView.getWidgets().filterIsInstance<ShellTerminalWidget >().firstOrNull {
146+ toolWindow?.getContentManager()?.getContent(it)?.isSelected ? : false
147+ }
148+
149+ if (widget != null ) {
150+ val textBuffer = widget.terminalTextBuffer
151+ val stringBuilder = StringBuilder ()
152+ // Iterate through all lines in the buffer (history + screen)
153+ for (i in 0 until textBuffer.historyLinesCount + textBuffer.screenLinesCount) {
154+ stringBuilder.append(textBuffer.getLine(i).text).append(' \n ' )
155+ }
156+ stringBuilder.toString()
157+ } else {
158+ " " // Return empty if no terminal is available
159+ }
160+ } catch (e: Exception ) {
161+ println (" Error getting terminal contents: ${e.message} " )
162+ e.printStackTrace()
163+ " " // Return empty on error
164+ }
165+ }
139166 }
140167
141168 override suspend fun getDebugLocals (threadIndex : Int ): String {
@@ -220,8 +247,65 @@ class IntelliJIDE(
220247 }
221248 }
222249
223- override suspend fun runCommand (command : String ) {
224- throw NotImplementedError (" runCommand not implemented in IntelliJ" )
250+ override suspend fun runCommand (command : String , options : TerminalOptions ? ) {
251+ val terminalOptions =
252+ options ? : TerminalOptions (reuseTerminal = true , terminalName = null , waitForCompletion = false )
253+
254+ ApplicationManager .getApplication().invokeLater {
255+ try {
256+ val toolWindow = ToolWindowManager .getInstance(project).getToolWindow(" Terminal" )
257+ toolWindow?.activate({
258+ try {
259+ val terminalView = TerminalView .getInstance(project)
260+ var widget: ShellTerminalWidget ? = null
261+
262+ // 1. Handle reuseTerminal option
263+ if (terminalOptions.reuseTerminal == true && terminalView.getWidgets().isNotEmpty()) {
264+ // 2. Find by terminalName if provided
265+ if (terminalOptions.terminalName != null ) {
266+ widget = terminalView.getWidgets().filterIsInstance<ShellTerminalWidget >()
267+ .firstOrNull {
268+ toolWindow.contentManager.getContent(it).tabName == terminalOptions.terminalName
269+ && ! it.hasRunningCommands()
270+ }
271+ } else {
272+ // 3. Find active terminal, or fall back to the first one
273+ widget = terminalView.getWidgets().filterIsInstance<ShellTerminalWidget >()
274+ .firstOrNull { toolWindow.contentManager.getContent(it).isSelected }
275+ ? : terminalView.getWidgets().filterIsInstance<ShellTerminalWidget >().firstOrNull {
276+ ! it.hasRunningCommands()
277+ }
278+ }
279+ }
280+
281+ // 4. Create a new terminal if needed
282+ if (widget == null ) {
283+ widget = terminalView.createLocalShellWidget(
284+ project.basePath,
285+ terminalOptions.terminalName,
286+ true
287+ )
288+ } else {
289+ // Ensure the found widget is visible
290+ val content = toolWindow.contentManager.getContent(widget)
291+ if (content != null ) {
292+ toolWindow.contentManager.setSelectedContent(content, true )
293+ }
294+ }
295+
296+ // 5. Show and send text
297+ widget.ttyConnector?.write(command)
298+
299+ } catch (e: Exception ) {
300+ println (" Error during terminal widget handling: ${e.message} " )
301+ e.printStackTrace()
302+ }
303+ }, true )
304+ } catch (e: Exception ) {
305+ println (" Error activating terminal tool window: ${e.message} " )
306+ e.printStackTrace()
307+ }
308+ }
225309 }
226310
227311 override suspend fun saveFile (filepath : String ) {
@@ -343,7 +427,7 @@ class IntelliJIDE(
343427 }
344428
345429 val command = GeneralCommandLine (commandArgs)
346-
430+
347431 command.setWorkDirectory(project.basePath)
348432 val results = ExecUtil .execAndGetOutput(command).stdout
349433 return results.split(" \n " )
@@ -357,11 +441,12 @@ class IntelliJIDE(
357441 throw NotImplementedError (" Ripgrep not supported, this workspace is remote" )
358442 }
359443 }
444+
360445 override suspend fun getSearchResults (query : String , maxResults : Int? ): String {
361446 val ideInfo = this .getIdeInfo()
362447 if (ideInfo.remoteName == " local" ) {
363448 try {
364- val commandArgs = mutableListOf (
449+ val commandArgs = mutableListOf (
365450 ripgrep,
366451 " -i" ,
367452 " --ignore-file" ,
@@ -372,20 +457,20 @@ class IntelliJIDE(
372457 " 2" ,
373458 " --heading"
374459 )
375-
460+
376461 // Conditionally add maxResults flag
377462 if (maxResults != null ) {
378463 commandArgs.add(" -m" )
379464 commandArgs.add(maxResults.toString())
380465 }
381-
466+
382467 // Add the search query and path
383468 commandArgs.add(" -e" )
384469 commandArgs.add(query)
385470 commandArgs.add(" ." )
386471
387472 val command = GeneralCommandLine (commandArgs)
388-
473+
389474 command.setWorkDirectory(project.basePath)
390475 return ExecUtil .execAndGetOutput(command).stdout
391476 } catch (exception: Exception ) {
0 commit comments