本文整理汇总了Golang中github.com/docker/docker/pkg/term.IsTerminal函数的典型用法代码示例。如果您正苦于以下问题:Golang IsTerminal函数的具体用法?Golang IsTerminal怎么用?Golang IsTerminal使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了IsTerminal函数的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的Golang代码示例。
示例1: Safe
// Safe invokes the provided function and will attempt to ensure that when the
// function returns (or a termination signal is sent) that the terminal state
// is reset to the condition it was in prior to the function being invoked. If
// t.Raw is true the terminal will be put into raw mode prior to calling the function.
// If the input file descriptor is not a TTY and TryDev is true, the /dev/tty file
// will be opened (if available).
func (t TTY) Safe(fn SafeFunc) error {
in := t.In
var hasFd bool
var inFd uintptr
if desc, ok := in.(fd); ok && in != nil {
inFd = desc.Fd()
hasFd = true
}
if t.TryDev && (!hasFd || !term.IsTerminal(inFd)) {
if f, err := os.Open("/dev/tty"); err == nil {
defer f.Close()
inFd = f.Fd()
hasFd = true
}
}
if !hasFd || !term.IsTerminal(inFd) {
return fn()
}
var state *term.State
var err error
if t.Raw {
state, err = term.MakeRaw(inFd)
} else {
state, err = term.SaveState(inFd)
}
if err != nil {
return err
}
return interrupt.Chain(t.Parent, func() { term.RestoreTerminal(inFd, state) }).Run(fn)
}
开发者ID:Clarifai,项目名称:kubernetes,代码行数:38,代码来源:term.go
示例2: withSafeTTYAndInterrupts
// withSafeTTYAndInterrupts invokes the provided function after the terminal
// state has been stored, and then on any error or termination attempts to
// restore the terminal state to its prior behavior. It also eats signals
// for the duration of the function.
func withSafeTTYAndInterrupts(fn func() error) error {
ch := make(chan os.Signal, 1)
signal.Notify(ch, childSignals...)
defer signal.Stop(ch)
inFd := os.Stdin.Fd()
if !term.IsTerminal(inFd) {
if f, err := os.Open("/dev/tty"); err == nil {
defer f.Close()
inFd = f.Fd()
}
}
if term.IsTerminal(inFd) {
state, err := term.SaveState(inFd)
if err != nil {
return err
}
go func() {
if _, ok := <-ch; !ok {
return
}
term.RestoreTerminal(inFd, state)
}()
defer term.RestoreTerminal(inFd, state)
return fn()
}
return fn()
}
开发者ID:johnmccawley,项目名称:origin,代码行数:33,代码来源:editor.go
示例3: NewDockerCli
func NewDockerCli(in io.ReadCloser, out, err io.Writer, key libtrust.PrivateKey, proto, addr string, tlsConfig *tls.Config) *DockerCli {
var (
inFd uintptr
outFd uintptr
isTerminalIn = false
isTerminalOut = false
scheme = "http"
)
if tlsConfig != nil {
scheme = "https"
}
if in != nil {
if file, ok := in.(*os.File); ok {
inFd = file.Fd()
isTerminalIn = term.IsTerminal(inFd)
}
}
if out != nil {
if file, ok := out.(*os.File); ok {
outFd = file.Fd()
isTerminalOut = term.IsTerminal(outFd)
}
}
if err == nil {
err = out
}
// The transport is created here for reuse during the client session
tr := &http.Transport{
TLSClientConfig: tlsConfig,
Dial: func(dial_network, dial_addr string) (net.Conn, error) {
// Why 32? See issue 8035
return net.DialTimeout(proto, addr, 32*time.Second)
},
}
if proto == "unix" {
// no need in compressing for local communications
tr.DisableCompression = true
}
return &DockerCli{
proto: proto,
addr: addr,
in: in,
out: out,
err: err,
key: key,
inFd: inFd,
outFd: outFd,
isTerminalIn: isTerminalIn,
isTerminalOut: isTerminalOut,
tlsConfig: tlsConfig,
scheme: scheme,
transport: tr,
}
}
开发者ID:baoruxing,项目名称:docker,代码行数:60,代码来源:cli.go
示例4: NewResponsiveWriter
// NewResponsiveWriter creates a Writer that detects the column width of the
// terminal we are in, and adjusts every line width to fit and use recommended
// terminal sizes for better readability. Does proper word wrapping automatically.
// if terminal width >= 120 columns use 120 columns
// if terminal width >= 100 columns use 100 columns
// if terminal width >= 80 columns use 80 columns
// In case we're not in a terminal or if it's smaller than 80 columns width,
// doesn't do any wrapping.
func NewResponsiveWriter(w io.Writer) io.Writer {
file, ok := w.(*os.File)
if !ok {
return w
}
fd := file.Fd()
if !term.IsTerminal(fd) {
return w
}
terminalSize := kterm.GetSize(fd)
if terminalSize == nil {
return w
}
var limit uint
switch {
case terminalSize.Width >= 120:
limit = 120
case terminalSize.Width >= 100:
limit = 100
case terminalSize.Width >= 80:
limit = 80
}
return NewWordWrapWriter(w, limit)
}
开发者ID:jayunit100,项目名称:origin,代码行数:35,代码来源:terminal_writer.go
示例5: NewDockerCli
func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string, tlsConfig *tls.Config) *DockerCli {
var (
isTerminal = false
terminalFd uintptr
scheme = "http"
)
if tlsConfig != nil {
scheme = "https"
}
if in != nil {
if file, ok := out.(*os.File); ok {
terminalFd = file.Fd()
isTerminal = term.IsTerminal(terminalFd)
}
}
if err == nil {
err = out
}
return &DockerCli{
proto: proto,
addr: addr,
in: in,
out: out,
err: err,
isTerminal: isTerminal,
terminalFd: terminalFd,
tlsConfig: tlsConfig,
scheme: scheme,
}
}
开发者ID:BreezeWu,项目名称:docker,代码行数:33,代码来源:cli.go
示例6: runPgRestore
func runPgRestore(args *docopt.Args, client controller.Client, config *runConfig) error {
config.Stdin = os.Stdin
var size int64
if filename := args.String["--file"]; filename != "" {
f, err := os.Open(filename)
if err != nil {
return err
}
defer f.Close()
stat, err := f.Stat()
if err != nil {
return err
}
size = stat.Size()
config.Stdin = f
}
if !args.Bool["--quiet"] && term.IsTerminal(os.Stderr.Fd()) {
bar := pb.New(0)
bar.SetUnits(pb.U_BYTES)
if size > 0 {
bar.Total = size
} else {
bar.ShowBar = false
}
bar.ShowSpeed = true
bar.Output = os.Stderr
bar.Start()
defer bar.Finish()
config.Stdin = bar.NewProxyReader(config.Stdin)
}
return pgRestore(client, config)
}
开发者ID:ably-forks,项目名称:flynn,代码行数:32,代码来源:pg.go
示例7: PromptForPasswordString
// PromptForPasswordString prompts for user input by disabling echo in terminal, useful for password prompt.
func PromptForPasswordString(r io.Reader, w io.Writer, format string, a ...interface{}) string {
if w == nil {
w = os.Stdout
}
if file, ok := r.(*os.File); ok {
inFd := file.Fd()
if term.IsTerminal(inFd) {
oldState, err := term.SaveState(inFd)
if err != nil {
glog.V(3).Infof("Unable to save terminal state")
return PromptForString(r, w, format, a...)
}
fmt.Fprintf(w, format, a...)
term.DisableEcho(inFd, oldState)
input := readInput(r)
defer term.RestoreTerminal(inFd, oldState)
fmt.Fprintf(w, "\n")
return input
}
glog.V(3).Infof("Stdin is not a terminal")
return PromptForString(r, w, format, a...)
}
return PromptForString(r, w, format, a...)
}
开发者ID:johnmccawley,项目名称:origin,代码行数:33,代码来源:terminal.go
示例8: Shell
func (client *NativeClient) Shell(args ...string) error {
var (
termWidth, termHeight int
)
conn, err := ssh.Dial("tcp", net.JoinHostPort(client.Hostname, strconv.Itoa(client.Port)), &client.Config)
if err != nil {
return err
}
defer closeConn(conn)
session, err := conn.NewSession()
if err != nil {
return err
}
defer session.Close()
session.Stdout = os.Stdout
session.Stderr = os.Stderr
session.Stdin = os.Stdin
modes := ssh.TerminalModes{
ssh.ECHO: 1,
}
fd := os.Stdin.Fd()
if term.IsTerminal(fd) {
oldState, err := term.MakeRaw(fd)
if err != nil {
return err
}
defer term.RestoreTerminal(fd, oldState)
winsize, err := term.GetWinsize(fd)
if err != nil {
termWidth = 80
termHeight = 24
} else {
termWidth = int(winsize.Width)
termHeight = int(winsize.Height)
}
}
if err := session.RequestPty("xterm", termHeight, termWidth, modes); err != nil {
return err
}
if len(args) == 0 {
if err := session.Shell(); err != nil {
return err
}
session.Wait()
} else {
session.Run(strings.Join(args, " "))
}
return nil
}
开发者ID:flavio,项目名称:machine,代码行数:60,代码来源:client.go
示例9: Safe
// Safe invokes the provided function and will attempt to ensure that when the
// function returns (or a termination signal is sent) that the terminal state
// is reset to the condition it was in prior to the function being invoked. If
// t.Raw is true the terminal will be put into raw mode prior to calling the function.
// If the input file descriptor is not a TTY and TryDev is true, the /dev/tty file
// will be opened (if available).
func (t TTY) Safe(fn SafeFunc) error {
inFd, isTerminal := term.GetFdInfo(t.In)
if !isTerminal && t.TryDev {
if f, err := os.Open("/dev/tty"); err == nil {
defer f.Close()
inFd = f.Fd()
isTerminal = term.IsTerminal(inFd)
}
}
if !isTerminal {
return fn()
}
var state *term.State
var err error
if t.Raw {
state, err = term.MakeRaw(inFd)
} else {
state, err = term.SaveState(inFd)
}
if err != nil {
return err
}
return interrupt.Chain(t.Parent, func() {
if t.sizeQueue != nil {
t.sizeQueue.stop()
}
term.RestoreTerminal(inFd, state)
}).Run(fn)
}
开发者ID:Xmagicer,项目名称:origin,代码行数:38,代码来源:term.go
示例10: runRedisDump
func runRedisDump(args *docopt.Args, client controller.Client, config *runConfig) error {
config.Stdout = os.Stdout
if filename := args.String["--file"]; filename != "" {
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
config.Stdout = f
}
if !args.Bool["--quiet"] && term.IsTerminal(os.Stderr.Fd()) {
bar := pb.New(0)
bar.SetUnits(pb.U_BYTES)
bar.ShowBar = false
bar.ShowSpeed = true
bar.Output = os.Stderr
bar.Start()
defer bar.Finish()
config.Stdout = io.MultiWriter(config.Stdout, bar)
}
config.Args[0] = "/bin/dump-flynn-redis"
return runJob(client, *config)
}
开发者ID:ably-forks,项目名称:flynn,代码行数:25,代码来源:redis.go
示例11: PromptRetriever
// PromptRetriever returns a new Retriever which will provide a prompt on stdin
// and stdout to retrieve a passphrase. stdin will be checked if it is a terminal,
// else the PromptRetriever will error when attempting to retrieve a passphrase.
// Upon successful passphrase retrievals, the passphrase will be cached such that
// subsequent prompts will produce the same passphrase.
func PromptRetriever() notary.PassRetriever {
if !term.IsTerminal(os.Stdin.Fd()) {
return func(string, string, bool, int) (string, bool, error) {
return "", false, ErrNoInput
}
}
return PromptRetrieverWithInOut(os.Stdin, os.Stdout, nil)
}
开发者ID:Mic92,项目名称:docker,代码行数:13,代码来源:passphrase.go
示例12: NewDockerCli
func NewDockerCli(in io.ReadCloser, out, err io.Writer, key libtrust.PrivateKey, proto, addr string, tlsConfig *tls.Config) *DockerCli {
var (
inFd uintptr
outFd uintptr
isTerminalIn = false
isTerminalOut = false
scheme = "http"
)
if tlsConfig != nil {
scheme = "https"
}
if in != nil {
if file, ok := in.(*os.File); ok {
inFd = file.Fd()
isTerminalIn = term.IsTerminal(inFd)
}
}
if out != nil {
if file, ok := out.(*os.File); ok {
outFd = file.Fd()
isTerminalOut = term.IsTerminal(outFd)
}
}
if err == nil {
err = out
}
return &DockerCli{
proto: proto,
addr: addr,
in: in,
out: out,
err: err,
key: key,
inFd: inFd,
outFd: outFd,
isTerminalIn: isTerminalIn,
isTerminalOut: isTerminalOut,
tlsConfig: tlsConfig,
scheme: scheme,
}
}
开发者ID:ericcapricorn,项目名称:deis,代码行数:46,代码来源:cli.go
示例13: Run
// Run executes a validated remote execution against a pod.
func (p *AttachOptions) Run() error {
pod, err := p.Client.Pods(p.Namespace).Get(p.PodName)
if err != nil {
return err
}
if pod.Status.Phase != api.PodRunning {
return fmt.Errorf("pod %s is not running and cannot be attached to; current phase is %s", p.PodName, pod.Status.Phase)
}
// TODO: refactor with terminal helpers from the edit utility once that is merged
var stdin io.Reader
tty := p.TTY
if p.Stdin {
stdin = p.In
if tty {
if file, ok := stdin.(*os.File); ok {
inFd := file.Fd()
if term.IsTerminal(inFd) {
oldState, err := term.SetRawTerminal(inFd)
if err != nil {
glog.Fatal(err)
}
// this handles a clean exit, where the command finished
defer term.RestoreTerminal(inFd, oldState)
// SIGINT is handled by term.SetRawTerminal (it runs a goroutine that listens
// for SIGINT and restores the terminal before exiting)
// this handles SIGTERM
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGTERM)
go func() {
<-sigChan
term.RestoreTerminal(inFd, oldState)
os.Exit(0)
}()
} else {
fmt.Fprintln(p.Err, "STDIN is not a terminal")
}
} else {
tty = false
fmt.Fprintln(p.Err, "Unable to use a TTY - input is not the right kind of file")
}
}
}
// TODO: consider abstracting into a client invocation or client helper
req := p.Client.RESTClient.Post().
Resource("pods").
Name(pod.Name).
Namespace(pod.Namespace).
SubResource("attach").
Param("container", p.GetContainerName(pod))
return p.Attach.Attach("POST", req.URL(), p.Config, stdin, p.Out, p.Err, tty)
}
开发者ID:niniwzw,项目名称:kubernetes,代码行数:58,代码来源:attach.go
示例14: Shell
func (client NativeClient) Shell() error {
var (
termWidth, termHeight int
)
conn, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", client.Hostname, client.Port), &client.Config)
if err != nil {
return err
}
session, err := conn.NewSession()
if err != nil {
return err
}
defer session.Close()
session.Stdout = os.Stdout
session.Stderr = os.Stderr
session.Stdin = os.Stdin
modes := ssh.TerminalModes{
ssh.ECHO: 1,
}
fd := os.Stdin.Fd()
if term.IsTerminal(fd) {
oldState, err := term.MakeRaw(fd)
if err != nil {
return err
}
defer term.RestoreTerminal(fd, oldState)
winsize, err := term.GetWinsize(fd)
if err != nil {
termWidth = 80
termHeight = 24
} else {
termWidth = int(winsize.Width)
termHeight = int(winsize.Height)
}
}
if err := session.RequestPty("xterm", termHeight, termWidth, modes); err != nil {
return err
}
if err := session.Shell(); err != nil {
return err
}
session.Wait()
return nil
}
开发者ID:jkingyens,项目名称:machine,代码行数:56,代码来源:client.go
示例15: Build
func (a *App) Build(e *env.Env, writer io.Writer) error {
e.Log.Info(`Build app`)
if a.Layer.ID == `` {
return errors.New("layer not found")
}
if err := a.Config.Sync(e, a.Layer.ID); err != nil {
return err
}
tar_path := fmt.Sprintf("%s/apps/%s", env.Default_root_path, a.Layer.ID)
reader, err := os.Open(tar_path)
if err != nil {
return err
}
or, ow := io.Pipe()
opts := interfaces.BuildImageOptions{
Name: a.Config.Image,
RmTmpContainer: true,
InputStream: reader,
OutputStream: ow,
RawJSONStream: true,
}
ch := make(chan error, 1)
go func() {
defer ow.Close()
defer close(ch)
if err := e.Containers.BuildImage(opts); err != nil {
e.Log.Error(err)
return
}
}()
jsonmessage.DisplayJSONMessagesStream(or, writer, os.Stdout.Fd(), term.IsTerminal(os.Stdout.Fd()), nil)
if err, ok := <-ch; ok {
if err != nil {
e.Log.Error(err)
return err
}
}
if err := a.Update(e); err != nil {
return err
}
reader.Close()
or.Close()
return nil
}
开发者ID:Gys,项目名称:deployit,代码行数:55,代码来源:app.go
示例16: Upload
func (g *Gist) Upload(log log15.Logger) error {
if len(g.Files) == 0 {
return errors.New("cannot create empty gist")
}
payload, err := json.Marshal(g)
if err != nil {
log.Error("error preparing gist content", "err", err)
return err
}
var body io.Reader = bytes.NewReader(payload)
if term.IsTerminal(os.Stderr.Fd()) {
bar := pb.New(len(payload))
bar.SetUnits(pb.U_BYTES)
bar.ShowSpeed = true
bar.Output = os.Stderr
bar.Start()
defer bar.Finish()
body = bar.NewProxyReader(body)
}
req, err := http.NewRequest("POST", "https://api.github.com/gists", body)
if err != nil {
log.Error("error preparing HTTP request", "err", err)
return err
}
req.Header.Set("Content-Type", "application/json")
log.Info("creating anonymous gist")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Error("error uploading gist content", "err", err)
return err
}
defer res.Body.Close()
if res.StatusCode != http.StatusCreated {
e := fmt.Sprintf("unexpected HTTP status: %d", res.StatusCode)
log.Error(e)
return errors.New(e)
}
if err := json.NewDecoder(res.Body).Decode(g); err != nil {
log.Error("error decoding HTTP response", "err", err)
return err
}
return nil
}
开发者ID:ably-forks,项目名称:flynn,代码行数:46,代码来源:gist.go
示例17: runArgs
func (d *Dapperfile) runArgs(tag, shell string, commandArgs []string) (string, []string) {
name := fmt.Sprintf("%s-%s", strings.Split(tag, ":")[0], randString())
args := []string{"-i", "--name", name}
if term.IsTerminal(0) {
args = append(args, "-t")
}
if d.env.Socket() || d.socket {
args = append(args, "-v", "/var/run/docker.sock:/var/run/docker.sock")
}
if d.IsBind() {
wd, err := os.Getwd()
if err == nil {
args = append(args, "-v", fmt.Sprintf("%s:%s", fmt.Sprintf("%s/%s", wd, d.env.Cp()), d.env.Source()))
}
}
args = append(args, "-e", fmt.Sprintf("DAPPER_UID=%d", os.Getuid()))
args = append(args, "-e", fmt.Sprintf("DAPPER_GID=%d", os.Getgid()))
for _, env := range d.env.Env() {
args = append(args, "-e", env)
}
if shell != "" {
args = append(args, "--entrypoint", shell)
args = append(args, "-e", "TERM")
}
args = append(args, d.env.RunArgs()...)
args = append(args, tag)
if shell != "" && len(commandArgs) == 0 {
args = append(args, "-")
} else {
args = append(args, commandArgs...)
}
return name, args
}
开发者ID:imikushin,项目名称:dapper,代码行数:43,代码来源:file.go
示例18: runClusterBackup
func runClusterBackup(args *docopt.Args) error {
client, err := getClusterClient()
if err != nil {
return err
}
var bar *pb.ProgressBar
var progress backup.ProgressBar
if term.IsTerminal(os.Stderr.Fd()) {
bar = pb.New(0)
bar.SetUnits(pb.U_BYTES)
bar.ShowBar = false
bar.ShowSpeed = true
bar.Output = os.Stderr
bar.Start()
progress = bar
}
var dest io.Writer = os.Stdout
if filename := args.String["--file"]; filename != "" {
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
dest = f
}
fmt.Fprintln(os.Stderr, "Creating cluster backup...")
if err := backup.Run(client, dest, progress); err != nil {
return err
}
if bar != nil {
bar.Finish()
}
fmt.Fprintln(os.Stderr, "Backup complete.")
return nil
}
开发者ID:ably-forks,项目名称:flynn,代码行数:40,代码来源:cluster.go
示例19: Basic
func (ps passwordStore) Basic(u *url.URL) (string, string) {
if ps.anonymous {
return "", ""
}
stdin := bufio.NewReader(os.Stdin)
fmt.Fprintf(os.Stdout, "Enter username: ")
userIn, err := stdin.ReadBytes('\n')
if err != nil {
logrus.Errorf("error processing username input: %s", err)
return "", ""
}
username := strings.TrimSpace(string(userIn))
if term.IsTerminal(0) {
state, err := term.SaveState(0)
if err != nil {
logrus.Errorf("error saving terminal state, cannot retrieve password: %s", err)
return "", ""
}
term.DisableEcho(0, state)
defer term.RestoreTerminal(0, state)
}
fmt.Fprintf(os.Stdout, "Enter password: ")
userIn, err = stdin.ReadBytes('\n')
fmt.Fprintln(os.Stdout)
if err != nil {
logrus.Errorf("error processing password input: %s", err)
return "", ""
}
password := strings.TrimSpace(string(userIn))
return username, password
}
开发者ID:cyli,项目名称:notary,代码行数:38,代码来源:tuf.go
示例20: requestPassphrase
func (br *boundRetriever) requestPassphrase(keyName, alias string, createNew bool, numAttempts int) (string, bool, error) {
// Figure out if we should display a different string for this alias
displayAlias := alias
if val, ok := br.aliasMap[alias]; ok {
displayAlias = val
}
// If typing on the terminal, we do not want the terminal to echo the
// password that is typed (so it doesn't display)
if term.IsTerminal(os.Stdin.Fd()) {
state, err := term.SaveState(os.Stdin.Fd())
if err != nil {
return "", false, err
}
term.DisableEcho(os.Stdin.Fd(), state)
defer term.RestoreTerminal(os.Stdin.Fd(), state)
}
indexOfLastSeparator := strings.LastIndex(keyName, string(filepath.Separator))
if indexOfLastSeparator == -1 {
indexOfLastSeparator = 0
}
var shortName string
if len(keyName) > indexOfLastSeparator+idBytesToDisplay {
if indexOfLastSeparator > 0 {
keyNamePrefix := keyName[:indexOfLastSeparator]
keyNameID := keyName[indexOfLastSeparator+1 : indexOfLastSeparator+idBytesToDisplay+1]
shortName = keyNameID + " (" + keyNamePrefix + ")"
} else {
shortName = keyName[indexOfLastSeparator : indexOfLastSeparator+idBytesToDisplay]
}
}
withID := fmt.Sprintf(" with ID %s", shortName)
if shortName == "" {
withID = ""
}
switch {
case createNew:
fmt.Fprintf(br.out, "Enter passphrase for new %s key%s: ", displayAlias, withID)
case displayAlias == "yubikey":
fmt.Fprintf(br.out, "Enter the %s for the attached Yubikey: ", keyName)
default:
fmt.Fprintf(br.out, "Enter passphrase for %s key%s: ", displayAlias, withID)
}
stdin := bufio.NewReader(br.in)
passphrase, err := stdin.ReadBytes('\n')
fmt.Fprintln(br.out)
if err != nil {
return "", false, err
}
retPass := strings.TrimSpace(string(passphrase))
if createNew {
err = br.verifyAndConfirmPassword(stdin, retPass, displayAlias, withID)
if err != nil {
return "", false, err
}
}
br.cachePassword(alias, retPass)
return retPass, false, nil
}
开发者ID:Mic92,项目名称:docker,代码行数:68,代码来源:passphrase.go
注:本文中的github.com/docker/docker/pkg/term.IsTerminal函数示例整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。 |
请发表评论