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
This repository was archived by the owner on Aug 30, 2024. It is now read-only.
/coder-v1-cliPublic archive

Commite775a2b

Browse files
authored
Merge pull request#79 from cdr/windows-tty
Adds support for windows
2 parents27020b7 +5a6b14e commite775a2b

File tree

9 files changed

+252
-53
lines changed

9 files changed

+252
-53
lines changed

‎.github/workflows/test.yaml

Whitespace-only changes.

‎ci/build.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ build(){
3030
if [["$(uname)"=="Darwin" ]];then
3131
GOOS=linux build
3232
CGO_ENABLED=1 GOOS=darwin build
33+
GOOS=windows GOARCH=386 build
3334
exit 0
3435
fi
3536

‎cmd/coder/main.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ import (
66
_"net/http/pprof"
77
"os"
88

9+
"cdr.dev/coder-cli/internal/xterminal"
910
"github.com/spf13/pflag"
1011

12+
"go.coder.com/flog"
13+
1114
"go.coder.com/cli"
1215
)
1316

@@ -48,5 +51,12 @@ func main() {
4851
log.Println(http.ListenAndServe("localhost:6060",nil))
4952
}()
5053
}
54+
55+
stdoutState,err:=xterminal.MakeOutputRaw(os.Stdout.Fd())
56+
iferr!=nil {
57+
flog.Fatal("failed to set output to raw: %v",err)
58+
}
59+
deferxterminal.Restore(os.Stdout.Fd(),stdoutState)
60+
5161
cli.RunRoot(&rootCmd{})
5262
}

‎cmd/coder/shell.go

Lines changed: 36 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,11 @@ import (
44
"context"
55
"io"
66
"os"
7-
"os/signal"
87
"strings"
98
"time"
109

1110
"github.com/spf13/pflag"
1211
"golang.org/x/crypto/ssh/terminal"
13-
"golang.org/x/sys/unix"
1412
"golang.org/x/time/rate"
1513
"golang.org/x/xerrors"
1614
"nhooyr.io/websocket"
@@ -19,6 +17,7 @@ import (
1917
"go.coder.com/flog"
2018

2119
"cdr.dev/coder-cli/internal/activity"
20+
"cdr.dev/coder-cli/internal/xterminal"
2221
"cdr.dev/wsep"
2322
)
2423

@@ -33,45 +32,8 @@ func (cmd *shellCmd) Spec() cli.CommandSpec {
3332
}
3433
}
3534

36-
funcenableTerminal(fdint) (restorefunc(),errerror) {
37-
state,err:=terminal.MakeRaw(fd)
38-
iferr!=nil {
39-
returnrestore,xerrors.Errorf("make raw term: %w",err)
40-
}
41-
returnfunc() {
42-
err:=terminal.Restore(fd,state)
43-
iferr!=nil {
44-
flog.Error("restore term state: %v",err)
45-
}
46-
},nil
47-
}
48-
49-
funcsendResizeEvents(ctx context.Context,termfdint,process wsep.Process) {
50-
sigs:=make(chan os.Signal,16)
51-
signal.Notify(sigs,unix.SIGWINCH)
52-
53-
// Limit the frequency of resizes to prevent a stuttering effect.
54-
resizeLimiter:=rate.NewLimiter(rate.Every(time.Millisecond*100),1)
55-
56-
forctx.Err()==nil {
57-
ifctx.Err()!=nil {
58-
return
59-
}
60-
width,height,err:=terminal.GetSize(termfd)
61-
iferr!=nil {
62-
flog.Error("get term size: %v",err)
63-
return
64-
}
65-
66-
err=process.Resize(ctx,uint16(height),uint16(width))
67-
iferr!=nil {
68-
return
69-
}
70-
71-
// Do this last so the first resize is sent.
72-
<-sigs
73-
resizeLimiter.Wait(ctx)
74-
}
35+
typeresizeEventstruct {
36+
height,widthuint16
7537
}
7638

7739
func (cmd*shellCmd)Run(fl*pflag.FlagSet) {
@@ -101,21 +63,40 @@ func (cmd *shellCmd) Run(fl *pflag.FlagSet) {
10163
}
10264
}
10365

66+
funcsendResizeEvents(ctx context.Context,termfduintptr,process wsep.Process) {
67+
events:=xterminal.ResizeEvents(ctx,termfd)
68+
69+
// Limit the frequency of resizes to prevent a stuttering effect.
70+
resizeLimiter:=rate.NewLimiter(rate.Every(time.Millisecond*100),1)
71+
for {
72+
select {
73+
casenewsize:=<-events:
74+
err:=process.Resize(ctx,newsize.Height,newsize.Width)
75+
iferr!=nil {
76+
return
77+
}
78+
_=resizeLimiter.Wait(ctx)
79+
case<-ctx.Done():
80+
return
81+
}
82+
}
83+
}
84+
10485
funcrunCommand(ctx context.Context,envNamestring,commandstring,args []string)error {
10586
var (
10687
entClient=requireAuth()
10788
env=findEnv(entClient,envName)
10889
)
10990

110-
termfd:=int(os.Stdin.Fd())
91+
termfd:=os.Stdout.Fd()
11192

112-
tty:=terminal.IsTerminal(termfd)
93+
tty:=terminal.IsTerminal(int(termfd))
11394
iftty {
114-
restore,err:=enableTerminal(termfd)
95+
stdinState,err:=xterminal.MakeRaw(os.Stdin.Fd())
11596
iferr!=nil {
11697
returnerr
11798
}
118-
deferrestore()
99+
deferxterminal.Restore(os.Stdin.Fd(),stdinState)
119100
}
120101

121102
ctx,cancel:=context.WithCancel(ctx)
@@ -127,13 +108,22 @@ func runCommand(ctx context.Context, envName string, command string, args []stri
127108
}
128109
goheartbeat(ctx,conn,15*time.Second)
129110

111+
varcmdEnv []string
112+
iftty {
113+
term:=os.Getenv("TERM")
114+
ifterm=="" {
115+
term="xterm"
116+
}
117+
cmdEnv=append(cmdEnv,"TERM="+term)
118+
}
119+
130120
execer:=wsep.RemoteExecer(conn)
131121
process,err:=execer.Start(ctx, wsep.Command{
132122
Command:command,
133123
Args:args,
134124
TTY:tty,
135125
Stdin:true,
136-
Env:[]string{"TERM="+os.Getenv("TERM")},
126+
Env:cmdEnv,
137127
})
138128
iferr!=nil {
139129
returnerr

‎go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module cdr.dev/coder-cli
33
go1.14
44

55
require (
6-
cdr.dev/wsepv0.0.0-20200616212001-0613cfe9a4ac
6+
cdr.dev/wsepv0.0.0-20200728013649-82316a09813f
77
github.com/fatih/colorv1.9.0// indirect
88
github.com/gorilla/websocketv1.4.1
99
github.com/kirsle/configdirv0.0.0-20170128060238-e45d2f54772f

‎go.sum

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
cdr.dev/slogv1.3.0 h1:MYN1BChIaVEGxdS7I5cpdyMC0+WfJfK8BETAfzfLUGQ=
22
cdr.dev/slogv1.3.0/go.mod h1:C5OL99WyuOK8YHZdYY57dAPN1jK2WJlCdq2VP6xeQns=
3-
cdr.dev/wsepv0.0.0-20200615020153-e2b1c576fc40 h1:f369880iSAZ3cXwvbdc9WIyy3FZ4yanusYZjaVHeis4=
4-
cdr.dev/wsepv0.0.0-20200615020153-e2b1c576fc40/go.mod h1:2VKClUml3gfmLez0gBxTJIjSKszpQotc2ZqPdApfK/Y=
5-
cdr.dev/wsepv0.0.0-20200616212001-0613cfe9a4ac h1:rl4O0qfxgNRWBUe5gQu4of2cdsclcpjGYmLQhSCHX7c=
6-
cdr.dev/wsepv0.0.0-20200616212001-0613cfe9a4ac/go.mod h1:2VKClUml3gfmLez0gBxTJIjSKszpQotc2ZqPdApfK/Y=
3+
cdr.dev/wsepv0.0.0-20200728013649-82316a09813f h1:WnTUINBwXE11xjp5nTVt+H2qB2/KEymos1jKMcppG9U=
4+
cdr.dev/wsepv0.0.0-20200728013649-82316a09813f/go.mod h1:2VKClUml3gfmLez0gBxTJIjSKszpQotc2ZqPdApfK/Y=
75
cloud.google.com/gov0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
86
cloud.google.com/gov0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
97
cloud.google.com/gov0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
@@ -240,8 +238,6 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w
240238
golang.org/x/sysv0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
241239
golang.org/x/sysv0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
242240
golang.org/x/sysv0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
243-
golang.org/x/sysv0.0.0-20200610111108-226ff32320da h1:bGb80FudwxpeucJUjPYJXuJ8Hk91vNtfvrymzwiei38=
244-
golang.org/x/sysv0.0.0-20200610111108-226ff32320da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
245241
golang.org/x/sysv0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
246242
golang.org/x/sysv0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
247243
golang.org/x/textv0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

‎internal/xterminal/doc.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Package xterminal provides functions to change termios or console attributes
2+
// and restore them later on. It supports Unix and Windows.
3+
//
4+
// This does the same thing as x/crypto/ssh/terminal on Linux. On Windows, it
5+
// sets the same console modes as the terminal package but also sets
6+
// `ENABLE_VIRTUAL_TERMINAL_INPUT` and `ENABLE_VIRTUAL_TERMINAL_PROCESSING` to
7+
// allow for VT100 sequences in the console. This is important, otherwise Linux
8+
// apps (with colors or ncurses) that are run through SSH or wsep get
9+
// garbled in a Windows console.
10+
//
11+
// More details can be found out about Windows console modes here:
12+
// https://docs.microsoft.com/en-us/windows/console/setconsolemode
13+
package xterminal

‎internal/xterminal/terminal.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// +build !windows
2+
3+
package xterminal
4+
5+
import (
6+
"context"
7+
"os"
8+
"os/signal"
9+
10+
"golang.org/x/crypto/ssh/terminal"
11+
"golang.org/x/sys/unix"
12+
)
13+
14+
// State differs per-platform.
15+
typeStatestruct {
16+
s*terminal.State
17+
}
18+
19+
// MakeRaw sets the terminal to raw.
20+
funcMakeRaw(fduintptr) (*State,error) {
21+
s,err:=terminal.MakeRaw(int(fd))
22+
return&State{s},err
23+
}
24+
25+
// MakeOutputRaw does nothing on non-Windows platforms.
26+
funcMakeOutputRaw(fduintptr) (*State,error) {
27+
returnnil,nil
28+
}
29+
30+
// Restore terminal back to original state.
31+
funcRestore(fduintptr,state*State)error {
32+
ifstate==nil {
33+
returnnil
34+
}
35+
36+
returnterminal.Restore(int(fd),state.s)
37+
}
38+
39+
// ColorEnabled returns true on Linux if handle is a terminal.
40+
funcColorEnabled(fduintptr) (bool,error) {
41+
returnterminal.IsTerminal(int(fd)),nil
42+
}
43+
44+
typeResizeEventstruct {
45+
Height,Widthuint16
46+
}
47+
48+
// ResizeEvents sends terminal resize events
49+
funcResizeEvents(ctx context.Context,termfduintptr)chanResizeEvent {
50+
sigs:=make(chan os.Signal,16)
51+
signal.Notify(sigs,unix.SIGWINCH)
52+
53+
events:=make(chanResizeEvent)
54+
55+
gofunc() {
56+
forctx.Err()==nil {
57+
width,height,err:=terminal.GetSize(int(termfd))
58+
iferr!=nil {
59+
return
60+
}
61+
events<-ResizeEvent{
62+
Height:uint16(height),
63+
Width:uint16(width),
64+
}
65+
66+
<-sigs
67+
}
68+
}()
69+
70+
returnevents
71+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp