[terminal] IJPL-182482 Extract LocalTerminalTtyConnector

This is a simple refactoring, needed to add more hooks
to the connector to implement output latency measuring.

GitOrigin-RevId: 6d3cfb6a679d7e72abdc5bd5e47b2cd5569c0ac7
This commit is contained in:
Sergei Tachenov
2025-04-15 07:32:52 +00:00
committed by intellij-monorepo-bot
parent c082a207f0
commit a9c2be092f
2 changed files with 68 additions and 46 deletions
@@ -7,14 +7,11 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.terminal.pty.PtyProcessTtyConnector;
import com.intellij.util.ArrayUtil;
import com.intellij.util.TimeoutUtil;
import com.intellij.util.concurrency.AppExecutorUtil;
import com.jediterm.core.util.TermSize;
import com.jediterm.terminal.TtyConnector;
import com.pty4j.PtyProcess;
import com.pty4j.unix.UnixPtyProcess;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -25,7 +22,6 @@ import org.jetbrains.plugins.terminal.runner.LocalOptionsConfigurer;
import org.jetbrains.plugins.terminal.runner.LocalShellIntegrationInjector;
import org.jetbrains.plugins.terminal.runner.LocalTerminalStartCommandBuilder;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
@@ -33,7 +29,6 @@ import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static org.jetbrains.plugins.terminal.LocalBlockTerminalRunner.*;
@@ -188,47 +183,7 @@ public class LocalTerminalDirectRunner extends AbstractTerminalRunner<PtyProcess
@Override
public @NotNull TtyConnector createTtyConnector(@NotNull PtyProcess process) {
return new PtyProcessTtyConnector(process, myDefaultCharset) {
@Override
public void write(byte[] bytes) throws IOException {
var fusActivity = ReworkedTerminalUsageCollector.getBackendTypingActivityOrNull(bytes);
try {
super.write(bytes);
if (fusActivity != null) {
fusActivity.reportDuration();
}
}
finally {
if (fusActivity != null) {
fusActivity.finishBytesProcessing();
}
}
}
@Override
public void close() {
if (process instanceof UnixPtyProcess) {
((UnixPtyProcess)process).hangup();
AppExecutorUtil.getAppScheduledExecutorService().schedule(() -> {
if (process.isAlive()) {
LOG.info("Terminal hasn't been terminated by SIGHUP, performing default termination");
process.destroy();
}
}, 1000, TimeUnit.MILLISECONDS);
}
else {
process.destroy();
}
}
@Override
public void resize(@NotNull TermSize termSize) {
if (LOG.isDebugEnabled()) {
LOG.debug("resize to " + termSize);
}
super.resize(termSize);
}
};
return new LocalTerminalTtyConnector(process, myDefaultCharset);
}
@Override
@@ -0,0 +1,67 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.terminal;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.terminal.pty.PtyProcessTtyConnector;
import com.intellij.util.concurrency.AppExecutorUtil;
import com.jediterm.core.util.TermSize;
import com.pty4j.PtyProcess;
import com.pty4j.unix.UnixPtyProcess;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.terminal.fus.ReworkedTerminalUsageCollector;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;
@ApiStatus.Internal
public class LocalTerminalTtyConnector extends PtyProcessTtyConnector {
private static final Logger LOG = Logger.getInstance(LocalTerminalTtyConnector.class);
private final @NotNull PtyProcess myProcess;
LocalTerminalTtyConnector(@NotNull PtyProcess process, @NotNull Charset charset) {
super(process, charset);
myProcess = process;
}
@Override
public void write(byte[] bytes) throws IOException {
var fusActivity = ReworkedTerminalUsageCollector.getBackendTypingActivityOrNull(bytes);
try {
super.write(bytes);
if (fusActivity != null) {
fusActivity.reportDuration();
}
}
finally {
if (fusActivity != null) {
fusActivity.finishBytesProcessing();
}
}
}
@Override
public void close() {
if (myProcess instanceof UnixPtyProcess) {
((UnixPtyProcess)myProcess).hangup();
AppExecutorUtil.getAppScheduledExecutorService().schedule(() -> {
if (myProcess.isAlive()) {
LOG.info("Terminal hasn't been terminated by SIGHUP, performing default termination");
myProcess.destroy();
}
}, 1000, TimeUnit.MILLISECONDS);
}
else {
myProcess.destroy();
}
}
@Override
public void resize(@NotNull TermSize termSize) {
if (LOG.isDebugEnabled()) {
LOG.debug("resize to " + termSize);
}
super.resize(termSize);
}
}