Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit963f4d0

Browse files
committed
feat: support shift+enter in terminal
It acts the same alt+enter, but is more familiar to users.
1 parent28789d7 commit963f4d0

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

‎site/src/pages/TerminalPage/TerminalPage.test.tsx‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import"jest-canvas-mock";
22
import{waitFor}from"@testing-library/react";
3+
importuserEventfrom"@testing-library/user-event";
34
import{API}from"api/api";
45
importWSfrom"jest-websocket-mock";
56
import{http,HttpResponse}from"msw";
@@ -148,4 +149,21 @@ describe("TerminalPage", () => {
148149
ws.send(text);
149150
awaitexpectTerminalText(container,text);
150151
});
152+
153+
it("supports shift+enter",async()=>{
154+
constws=newWS(
155+
`ws://localhost/api/v2/workspaceagents/${MockWorkspaceAgent.id}/pty`,
156+
);
157+
158+
const{ container}=awaitrenderTerminal();
159+
// Ideally we could use ws.connected but that seems to pause React updates.
160+
// For now, wait for the initial resize message instead.
161+
awaitws.nextMessage;
162+
163+
constmsg=ws.nextMessage;
164+
constterminal=container.getElementsByClassName("xterm");
165+
awaituserEvent.type(terminal[0],"{Shift>}{Enter}{/Shift}");
166+
constreq=JSON.parse(newTextDecoder().decode((awaitmsg)asUint8Array));
167+
expect(req.data).toBe("\x1b\r");
168+
});
151169
});

‎site/src/pages/TerminalPage/TerminalPage.tsx‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,22 @@ const TerminalPage: FC = () => {
148148
}),
149149
);
150150

151+
// Make shift+enter send ^[^M (escaped carriage return). Applications
152+
// typically take this to mean to insert a literal newline. There is no way
153+
// to remove this handler, so we must attach it once and rely on a ref to
154+
// send it to the current socket.
155+
terminal.attachCustomKeyEventHandler((ev)=>{
156+
if(ev.shiftKey&&ev.key==="Enter"){
157+
if(ev.type==="keydown"){
158+
websocketRef.current?.send(
159+
newTextEncoder().encode(JSON.stringify({data:"\x1b\r"})),
160+
);
161+
}
162+
returnfalse;
163+
}
164+
returntrue;
165+
});
166+
151167
terminal.open(terminalWrapperRef.current);
152168

153169
// We have to fit twice here. It's unknown why, but the first fit will
@@ -190,6 +206,7 @@ const TerminalPage: FC = () => {
190206
},[navigate,reconnectionToken,searchParams]);
191207

192208
// Hook up the terminal through a web socket.
209+
constwebsocketRef=useRef<Websocket>();
193210
useEffect(()=>{
194211
if(!terminal){
195212
return;
@@ -270,6 +287,7 @@ const TerminalPage: FC = () => {
270287
.withBackoff(newExponentialBackoff(1000,6))
271288
.build();
272289
websocket.binaryType="arraybuffer";
290+
websocketRef.current=websocket;
273291
websocket.addEventListener(WebsocketEvent.open,()=>{
274292
// Now that we are connected, allow user input.
275293
terminal.options={
@@ -333,6 +351,7 @@ const TerminalPage: FC = () => {
333351
d.dispose();
334352
}
335353
websocket?.close(1000);
354+
websocketRef.current=undefined;
336355
};
337356
},[
338357
command,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp