Files
asciinema/commands/rec.go

140 lines
2.6 KiB
Go
Raw Normal View History

2014-08-03 19:50:39 +02:00
package commands
import (
"flag"
"fmt"
"os"
2014-11-02 19:04:19 +01:00
"time"
2014-08-03 19:50:39 +02:00
"github.com/asciinema/asciinema-cli/api"
"github.com/asciinema/asciinema-cli/cli"
"github.com/asciinema/asciinema-cli/terminal"
"github.com/asciinema/asciinema-cli/util"
)
2014-11-12 20:54:50 +01:00
type RecordCommand struct {
Cfg *util.Config
2014-11-15 13:33:20 +01:00
API api.API
2014-11-12 20:54:50 +01:00
Terminal terminal.Terminal
Command string
Title string
NoConfirm bool
}
2014-11-15 13:33:20 +01:00
func NewRecordCommand(api api.API, cfg *util.Config) cli.Command {
2014-11-12 20:54:50 +01:00
return &RecordCommand{
2014-11-15 13:33:20 +01:00
API: api,
2014-11-12 20:54:50 +01:00
Cfg: cfg,
2014-08-03 20:48:48 +02:00
Terminal: terminal.New(),
}
2014-11-12 20:54:50 +01:00
}
2014-08-03 19:50:39 +02:00
2014-11-12 20:54:50 +01:00
func (c *RecordCommand) RegisterFlags(flags *flag.FlagSet) {
2014-08-03 19:50:39 +02:00
flags.StringVar(
2014-11-12 20:54:50 +01:00
&c.Command,
2014-08-03 19:50:39 +02:00
"c",
2014-11-12 20:54:50 +01:00
defaultRecCommand(c.Cfg.Record.Command),
2014-08-03 19:50:39 +02:00
"command to record, defaults to $SHELL",
)
flags.StringVar(
2014-11-12 20:54:50 +01:00
&c.Title,
2014-08-03 19:50:39 +02:00
"t",
"",
"set title of the asciicast",
)
flags.BoolVar(
2014-11-12 20:54:50 +01:00
&c.NoConfirm,
2014-08-03 19:50:39 +02:00
"y",
false,
"upload without asking for confirmation",
2014-08-03 19:50:39 +02:00
)
}
func (c *RecordCommand) Execute(args []string) error {
rows, cols, _ := c.Terminal.Size()
if rows > 30 || cols > 120 {
util.Warningf("Current terminal size is %vx%v.", cols, rows)
util.Warningf("It may be too big to be properly replayed on smaller screens.")
util.Warningf("You can now resize it. Press <Enter> to start recording.")
2014-08-03 20:57:15 +02:00
util.ReadLine()
2014-08-03 19:50:39 +02:00
}
util.Printf("Asciicast recording started.")
2014-11-02 19:04:19 +01:00
util.Printf(`Hit ctrl-d or type "exit" to finish.`)
2014-08-03 19:50:39 +02:00
2014-11-02 19:04:19 +01:00
stdout := NewStream()
2014-08-03 19:50:39 +02:00
err := c.Terminal.Record(c.Command, stdout)
if err != nil {
return err
}
2014-11-02 19:04:19 +01:00
stdout.Close()
2014-08-03 19:50:39 +02:00
util.Printf("Asciicast recording finished.")
2014-08-09 21:52:00 +02:00
if !c.NoConfirm {
util.Printf("Press <Enter> to upload, <Ctrl-C> to cancel.")
util.ReadLine()
}
2014-08-03 19:50:39 +02:00
rows, cols, _ = c.Terminal.Size()
2014-11-15 13:33:20 +01:00
url, err := c.API.CreateAsciicast(stdout.Frames, stdout.Duration(), cols, rows, c.Command, c.Title)
2014-08-03 19:50:39 +02:00
if err != nil {
return err
}
fmt.Println(url)
return nil
}
func defaultRecCommand(recCommand string) string {
if recCommand == "" {
recCommand = os.Getenv("SHELL")
if recCommand == "" {
recCommand = "/bin/sh"
}
}
return recCommand
}
2014-11-02 19:04:19 +01:00
type Stream struct {
Frames []api.Frame
startTime time.Time
lastWriteTime time.Time
2014-08-03 19:50:39 +02:00
}
2014-11-02 19:04:19 +01:00
func NewStream() *Stream {
now := time.Now()
return &Stream{
startTime: now,
lastWriteTime: now,
}
}
func (s *Stream) Write(p []byte) (int, error) {
now := time.Now()
frame := api.Frame{}
frame.Delay = now.Sub(s.lastWriteTime).Seconds()
frame.Data = make([]byte, len(p))
copy(frame.Data, p)
s.Frames = append(s.Frames, frame)
s.lastWriteTime = now
2014-08-03 19:50:39 +02:00
return len(p), nil
}
2014-11-02 19:04:19 +01:00
func (s *Stream) Close() {
s.lastWriteTime = time.Now()
}
func (s *Stream) Duration() time.Duration {
return s.lastWriteTime.Sub(s.startTime)
2014-08-03 19:50:39 +02:00
}