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

Adds support for windows#79

Merged
cmoog merged 3 commits intomasterfromwindows-tty
Jul 28, 2020
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added.github/workflows/test.yaml
View file
Open in desktop
Empty file.
1 change: 1 addition & 0 deletionsci/build.sh
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,6 +30,7 @@ build(){
if [[ "$(uname)" == "Darwin" ]]; then
GOOS=linux build
CGO_ENABLED=1 GOOS=darwin build
GOOS=windows GOARCH=386 build
exit 0
fi

Expand Down
10 changes: 10 additions & 0 deletionscmd/coder/main.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,8 +6,11 @@ import (
_ "net/http/pprof"
"os"

"cdr.dev/coder-cli/internal/xterminal"
"github.com/spf13/pflag"

"go.coder.com/flog"

"go.coder.com/cli"
)

Expand DownExpand Up@@ -48,5 +51,12 @@ func main() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
}

stdoutState, err := xterminal.MakeOutputRaw(os.Stdout.Fd())
if err != nil {
flog.Fatal("failed to set output to raw: %v", err)
}
defer xterminal.Restore(os.Stdout.Fd(), stdoutState)

cli.RunRoot(&rootCmd{})
}
82 changes: 36 additions & 46 deletionscmd/coder/shell.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,13 +4,11 @@ import (
"context"
"io"
"os"
"os/signal"
"strings"
"time"

"github.com/spf13/pflag"
"golang.org/x/crypto/ssh/terminal"
"golang.org/x/sys/unix"
"golang.org/x/time/rate"
"golang.org/x/xerrors"
"nhooyr.io/websocket"
Expand All@@ -19,6 +17,7 @@ import (
"go.coder.com/flog"

"cdr.dev/coder-cli/internal/activity"
"cdr.dev/coder-cli/internal/xterminal"
"cdr.dev/wsep"
)

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

func enableTerminal(fd int) (restore func(), err error) {
state, err := terminal.MakeRaw(fd)
if err != nil {
return restore, xerrors.Errorf("make raw term: %w", err)
}
return func() {
err := terminal.Restore(fd, state)
if err != nil {
flog.Error("restore term state: %v", err)
}
}, nil
}

func sendResizeEvents(ctx context.Context, termfd int, process wsep.Process) {
sigs := make(chan os.Signal, 16)
signal.Notify(sigs, unix.SIGWINCH)

// Limit the frequency of resizes to prevent a stuttering effect.
resizeLimiter := rate.NewLimiter(rate.Every(time.Millisecond*100), 1)

for ctx.Err() == nil {
if ctx.Err() != nil {
return
}
width, height, err := terminal.GetSize(termfd)
if err != nil {
flog.Error("get term size: %v", err)
return
}

err = process.Resize(ctx, uint16(height), uint16(width))
if err != nil {
return
}

// Do this last so the first resize is sent.
<-sigs
resizeLimiter.Wait(ctx)
}
type resizeEvent struct {
height, width uint16
}

func (cmd *shellCmd) Run(fl *pflag.FlagSet) {
Expand DownExpand Up@@ -101,21 +63,40 @@ func (cmd *shellCmd) Run(fl *pflag.FlagSet) {
}
}

func sendResizeEvents(ctx context.Context, termfd uintptr, process wsep.Process) {
events := xterminal.ResizeEvents(ctx, termfd)

// Limit the frequency of resizes to prevent a stuttering effect.
resizeLimiter := rate.NewLimiter(rate.Every(time.Millisecond*100), 1)
for {
select {
case newsize := <-events:
err := process.Resize(ctx, newsize.Height, newsize.Width)
if err != nil {
return
}
_ = resizeLimiter.Wait(ctx)
case <-ctx.Done():
return
}
}
}

func runCommand(ctx context.Context, envName string, command string, args []string) error {
var (
entClient = requireAuth()
env = findEnv(entClient, envName)
)

termfd :=int(os.Stdin.Fd())
termfd := os.Stdout.Fd()

tty := terminal.IsTerminal(termfd)
tty := terminal.IsTerminal(int(termfd))
if tty {
restore, err :=enableTerminal(termfd)
stdinState, err :=xterminal.MakeRaw(os.Stdin.Fd())
if err != nil {
return err
}
deferrestore()
deferxterminal.Restore(os.Stdin.Fd(), stdinState)
}

ctx, cancel := context.WithCancel(ctx)
Expand All@@ -127,13 +108,22 @@ func runCommand(ctx context.Context, envName string, command string, args []stri
}
go heartbeat(ctx, conn, 15*time.Second)

var cmdEnv []string
if tty {
term := os.Getenv("TERM")
if term == "" {
term = "xterm"
}
cmdEnv = append(cmdEnv, "TERM="+term)
}

execer := wsep.RemoteExecer(conn)
process, err := execer.Start(ctx, wsep.Command{
Command: command,
Args: args,
TTY: tty,
Stdin: true,
Env:[]string{"TERM=" + os.Getenv("TERM")},
Env:cmdEnv,
})
if err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletiongo.mod
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,7 +3,7 @@ module cdr.dev/coder-cli
go 1.14

require (
cdr.dev/wsep v0.0.0-20200616212001-0613cfe9a4ac
cdr.dev/wsep v0.0.0-20200728013649-82316a09813f
github.com/fatih/color v1.9.0 // indirect
github.com/gorilla/websocket v1.4.1
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f
Expand Down
8 changes: 2 additions & 6 deletionsgo.sum
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
cdr.dev/slog v1.3.0 h1:MYN1BChIaVEGxdS7I5cpdyMC0+WfJfK8BETAfzfLUGQ=
cdr.dev/slog v1.3.0/go.mod h1:C5OL99WyuOK8YHZdYY57dAPN1jK2WJlCdq2VP6xeQns=
cdr.dev/wsep v0.0.0-20200615020153-e2b1c576fc40 h1:f369880iSAZ3cXwvbdc9WIyy3FZ4yanusYZjaVHeis4=
cdr.dev/wsep v0.0.0-20200615020153-e2b1c576fc40/go.mod h1:2VKClUml3gfmLez0gBxTJIjSKszpQotc2ZqPdApfK/Y=
cdr.dev/wsep v0.0.0-20200616212001-0613cfe9a4ac h1:rl4O0qfxgNRWBUe5gQu4of2cdsclcpjGYmLQhSCHX7c=
cdr.dev/wsep v0.0.0-20200616212001-0613cfe9a4ac/go.mod h1:2VKClUml3gfmLez0gBxTJIjSKszpQotc2ZqPdApfK/Y=
cdr.dev/wsep v0.0.0-20200728013649-82316a09813f h1:WnTUINBwXE11xjp5nTVt+H2qB2/KEymos1jKMcppG9U=
cdr.dev/wsep v0.0.0-20200728013649-82316a09813f/go.mod h1:2VKClUml3gfmLez0gBxTJIjSKszpQotc2ZqPdApfK/Y=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
Expand DownExpand Up@@ -240,8 +238,6 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200610111108-226ff32320da h1:bGb80FudwxpeucJUjPYJXuJ8Hk91vNtfvrymzwiei38=
golang.org/x/sys v0.0.0-20200610111108-226ff32320da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
13 changes: 13 additions & 0 deletionsinternal/xterminal/doc.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
// Package xterminal provides functions to change termios or console attributes
// and restore them later on. It supports Unix and Windows.
//
// This does the same thing as x/crypto/ssh/terminal on Linux. On Windows, it
// sets the same console modes as the terminal package but also sets
// `ENABLE_VIRTUAL_TERMINAL_INPUT` and `ENABLE_VIRTUAL_TERMINAL_PROCESSING` to
// allow for VT100 sequences in the console. This is important, otherwise Linux
// apps (with colors or ncurses) that are run through SSH or wsep get
// garbled in a Windows console.
//
// More details can be found out about Windows console modes here:
// https://docs.microsoft.com/en-us/windows/console/setconsolemode
package xterminal
71 changes: 71 additions & 0 deletionsinternal/xterminal/terminal.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
// +build !windows

package xterminal

import (
"context"
"os"
"os/signal"

"golang.org/x/crypto/ssh/terminal"
"golang.org/x/sys/unix"
)

// State differs per-platform.
type State struct {
s *terminal.State
}

// MakeRaw sets the terminal to raw.
func MakeRaw(fd uintptr) (*State, error) {
s, err := terminal.MakeRaw(int(fd))
return &State{s}, err
}

// MakeOutputRaw does nothing on non-Windows platforms.
func MakeOutputRaw(fd uintptr) (*State, error) {
return nil, nil
}

// Restore terminal back to original state.
func Restore(fd uintptr, state *State) error {
if state == nil {
return nil
}

return terminal.Restore(int(fd), state.s)
}

// ColorEnabled returns true on Linux if handle is a terminal.
func ColorEnabled(fd uintptr) (bool, error) {
return terminal.IsTerminal(int(fd)), nil
}

type ResizeEvent struct {
Height, Width uint16
}

// ResizeEvents sends terminal resize events
func ResizeEvents(ctx context.Context, termfd uintptr) chan ResizeEvent {
sigs := make(chan os.Signal, 16)
signal.Notify(sigs, unix.SIGWINCH)

events := make(chan ResizeEvent)

go func() {
for ctx.Err() == nil {
width, height, err := terminal.GetSize(int(termfd))
if err != nil {
return
}
events <- ResizeEvent{
Height: uint16(height),
Width: uint16(width),
}

<-sigs
}
}()

return events
}
Loading

[8]ページ先頭

©2009-2025 Movatter.jp