[terminal] IJPL-192386 Add an ability to get terminal text from the TerminalWidget

Support the classic terminal, new terminal (gen1) and the reworked terminal (gen2).
This method is the fast solution, but probably not final, since we plan to have a better public API for the Reworked Terminal. So, mark it as experimental.


(cherry picked from commit 1bae3499a909b4b9447af0b734a87eda53e8d67d)

IJ-CR-166213

GitOrigin-RevId: f0b7e77880e38ef3d2ac4b1c4ba19e99fcc7da06
This commit is contained in:
Konstantin Hudyakov
2025-06-18 10:56:09 +03:00
committed by intellij-monorepo-bot
parent dd37482966
commit 5c55ca407e
11 changed files with 57 additions and 0 deletions

View File

@@ -25,4 +25,5 @@ f:com.intellij.execution.util.EnvFilesUtilKt
com.intellij.terminal.ui.TerminalWidget
- com.intellij.openapi.ui.ComponentContainer
- *a:getTerminalSizeInitializedFuture():java.util.concurrent.CompletableFuture
- *:getText():java.lang.CharSequence
- *:isCommandRunning():Z

View File

@@ -429,6 +429,11 @@ public class JBTerminalWidget extends JediTermWidget implements Disposable, UiCo
}
}
@Override
public @NotNull CharSequence getText() {
return widget().getText();
}
@Override
public boolean isCommandRunning() {
try {

View File

@@ -72,6 +72,15 @@ interface TerminalWidget : ComponentContainer {
@RequiresEdt(generateAssertion = false)
fun sendCommandToExecute(shellCommand: String)
/**
* Returns the **immutable** state of the terminal output text.
*/
@ApiStatus.Experimental
@RequiresEdt(generateAssertion = false)
fun getText(): CharSequence {
return ""
}
/**
* Note that implementations might not guarantee that the result is 100% correct.
*/

View File

@@ -199,6 +199,10 @@ internal class ReworkedTerminalView(
terminalInput.sendBytes(bytes)
}
override fun getText(): CharSequence {
return getCurEditor().document.immutableCharSequence
}
override fun isCommandRunning(): Boolean {
// Will work only if there is a shell integration.
// If there is no shell integration, then it is always false.

View File

@@ -68,6 +68,10 @@ internal class ReworkedTerminalWidget(
view.sendCommandToExecute(shellCommand)
}
override fun getText(): CharSequence {
return view.getText()
}
override fun isCommandRunning(): Boolean {
return view.isCommandRunning()
}

View File

@@ -294,6 +294,14 @@ class BlockTerminalView(
controller.startCommandExecution(shellCommand)
}
override fun getText(): CharSequence {
alternateBufferView?.let { return it.getText() }
val outputText = outputView.controller.outputModel.editor.document.text
val promptText = promptView.controller.model.editor.document.text
return "$outputText\n$promptText"
}
override fun dispose() {}
private fun getDisposed(): () -> Boolean = outputView.controller.outputModel.editor.getDisposed()

View File

@@ -57,5 +57,9 @@ internal class OldPlainTerminalView(project: Project,
widget.executeCommand(shellCommand)
}
override fun getText(): CharSequence {
return widget.text
}
override fun dispose() {}
}

View File

@@ -73,5 +73,9 @@ internal class PlainTerminalView(
session.commandExecutionManager.sendCommandToExecute(shellCommand)
}
override fun getText(): CharSequence {
return view.getText()
}
override fun dispose() {}
}

View File

@@ -81,6 +81,10 @@ internal class SimpleTerminalView(
fun isFocused(): Boolean = editor.contentComponent.hasFocus()
fun getText(): CharSequence {
return editor.document.immutableCharSequence
}
override fun dispose() {
EditorFactory.getInstance().releaseEditor(editor)
Disposer.dispose(controller)

View File

@@ -32,6 +32,12 @@ interface TerminalContentView : Disposable {
@RequiresEdt(generateAssertion = false)
fun sendCommandToExecute(shellCommand: String)
/**
* Returns the **immutable** state of the terminal output text.
*/
@RequiresEdt(generateAssertion = false)
fun getText(): CharSequence
@RequiresEdt(generateAssertion = false)
fun isCommandRunning(): Boolean {
return false

View File

@@ -124,6 +124,10 @@ internal class TerminalWidgetImpl(
view.sendCommandToExecute(shellCommand)
}
override fun getText(): CharSequence {
return view.getText()
}
override fun isCommandRunning(): Boolean {
val connector = ttyConnector ?: return false
return TerminalUtil.hasRunningCommands(connector)
@@ -181,6 +185,10 @@ internal class TerminalWidgetImpl(
postponedShellCommands.add(shellCommand)
}
override fun getText(): CharSequence {
return ""
}
fun moveTerminationCallbacksTo(destView: TerminalContentView) {
for (info in postponedTerminationCallbackInfos) {
destView.addTerminationCallback(info.first, info.second)