2015-02-24 16:22:31 +01:00
|
|
|
package asciicast
|
|
|
|
|
|
|
|
|
|
import (
|
2016-02-03 22:49:49 -08:00
|
|
|
"fmt"
|
|
|
|
|
"os"
|
|
|
|
|
"os/signal"
|
|
|
|
|
"syscall"
|
|
|
|
|
|
2015-03-05 15:57:12 +01:00
|
|
|
"github.com/asciinema/asciinema/terminal"
|
|
|
|
|
"github.com/asciinema/asciinema/util"
|
2015-02-24 16:22:31 +01:00
|
|
|
)
|
|
|
|
|
|
2016-02-03 22:49:49 -08:00
|
|
|
const (
|
2016-02-13 21:12:35 -08:00
|
|
|
warnCols = 120
|
|
|
|
|
warnRows = 30
|
2016-02-03 22:49:49 -08:00
|
|
|
)
|
|
|
|
|
|
2015-02-24 16:22:31 +01:00
|
|
|
type Recorder interface {
|
2016-05-15 20:18:00 +02:00
|
|
|
Record(string, string, string, float64, bool, map[string]string) error
|
2015-02-24 16:22:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type AsciicastRecorder struct {
|
|
|
|
|
Terminal terminal.Terminal
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewRecorder() Recorder {
|
|
|
|
|
return &AsciicastRecorder{Terminal: terminal.NewTerminal()}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-03 22:49:49 -08:00
|
|
|
func (r *AsciicastRecorder) checkTerminalSize() chan<- bool {
|
|
|
|
|
rows, cols, _ := r.Terminal.Size()
|
|
|
|
|
doneChan := make(chan bool)
|
|
|
|
|
go func() {
|
|
|
|
|
winch := make(chan os.Signal, 1)
|
|
|
|
|
signal.Notify(winch, syscall.SIGWINCH)
|
|
|
|
|
|
|
|
|
|
defer signal.Stop(winch)
|
|
|
|
|
defer close(winch)
|
|
|
|
|
defer close(doneChan)
|
|
|
|
|
|
|
|
|
|
for {
|
|
|
|
|
select {
|
|
|
|
|
case <-winch:
|
|
|
|
|
newRows, newCols, _ := r.Terminal.Size()
|
|
|
|
|
if cols != newCols || rows != newRows {
|
|
|
|
|
cols, rows = newCols, newRows
|
|
|
|
|
currentSize := fmt.Sprintf("%dx%d", cols, rows)
|
2016-02-13 21:12:35 -08:00
|
|
|
util.ReplaceWarningf("Current terminal size is %s.", currentSize)
|
2016-02-03 22:49:49 -08:00
|
|
|
}
|
|
|
|
|
case <-doneChan:
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
return doneChan
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-15 20:18:00 +02:00
|
|
|
func (r *AsciicastRecorder) Record(path, command, title string, maxWait float64, assumeYes bool, env map[string]string) error {
|
2015-02-24 16:22:31 +01:00
|
|
|
// TODO: touch savePath to ensure writing is possible
|
|
|
|
|
|
|
|
|
|
rows, cols, _ := r.Terminal.Size()
|
2016-02-13 21:12:35 -08:00
|
|
|
if rows > warnRows || cols > warnCols {
|
2015-03-07 18:35:50 +01:00
|
|
|
if !assumeYes {
|
2016-02-03 22:49:49 -08:00
|
|
|
doneChan := r.checkTerminalSize()
|
2016-02-13 21:12:35 -08:00
|
|
|
util.Warningf("Current terminal size is %vx%v.", cols, rows)
|
|
|
|
|
util.Warningf("It may be too big to be properly replayed on smaller screens.")
|
2015-03-07 18:35:50 +01:00
|
|
|
util.Warningf("You can now resize it. Press <Enter> to start recording.")
|
|
|
|
|
util.ReadLine()
|
2016-02-03 22:49:49 -08:00
|
|
|
doneChan <- true
|
2015-03-07 18:35:50 +01:00
|
|
|
}
|
2015-02-24 16:22:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
util.Printf("Asciicast recording started.")
|
|
|
|
|
util.Printf(`Hit Ctrl-D or type "exit" to finish.`)
|
|
|
|
|
|
|
|
|
|
stdout := NewStream(maxWait)
|
|
|
|
|
|
|
|
|
|
err := r.Terminal.Record(command, stdout)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stdout.Close()
|
|
|
|
|
|
|
|
|
|
util.Printf("Asciicast recording finished.")
|
|
|
|
|
|
|
|
|
|
rows, cols, _ = r.Terminal.Size()
|
|
|
|
|
|
2015-03-02 10:52:28 +01:00
|
|
|
asciicast := NewAsciicast(
|
|
|
|
|
cols,
|
|
|
|
|
rows,
|
|
|
|
|
stdout.Duration().Seconds(),
|
|
|
|
|
command,
|
|
|
|
|
title,
|
|
|
|
|
stdout.Frames,
|
2015-03-11 12:07:26 +01:00
|
|
|
env,
|
2015-03-02 10:52:28 +01:00
|
|
|
)
|
2015-02-24 16:22:31 +01:00
|
|
|
|
|
|
|
|
err = Save(asciicast, path)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|