chore: lint and govuln (#775)
build / build (push) Failing after 0s
build / snapshot (push) Failing after 0s
lint / lint (push) Failing after 1s
nightly / nightly (push) Failing after 0s
build / build (push) Failing after 0s
build / snapshot (push) Failing after 0s
lint / lint (push) Failing after 1s
nightly / nightly (push) Failing after 0s
Signed-off-by: drew <me@andrinoff.com>
This commit is contained in:
+4
-1
@@ -456,6 +456,9 @@ func ExecutePaste(_ parser.Command, v *VHS) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// shellSetting is the name of the setting that configures the shell.
|
||||
const shellSetting = "Shell"
|
||||
|
||||
// Settings maps the Set commands to their respective functions.
|
||||
var Settings = map[string]CommandFunc{
|
||||
"FontFamily": ExecuteSetFontFamily,
|
||||
@@ -469,7 +472,7 @@ var Settings = map[string]CommandFunc{
|
||||
"Theme": ExecuteSetTheme,
|
||||
"TypingSpeed": ExecuteSetTypingSpeed,
|
||||
"Width": ExecuteSetWidth,
|
||||
"Shell": ExecuteSetShell,
|
||||
shellSetting: ExecuteSetShell,
|
||||
"LoopOffset": ExecuteLoopOffset,
|
||||
"MarginFill": ExecuteSetMarginFill,
|
||||
"Margin": ExecuteSetMargin,
|
||||
|
||||
+5
-5
@@ -30,7 +30,7 @@ func Evaluate(ctx context.Context, tape string, out io.Writer, opts ...Evaluator
|
||||
|
||||
v := New()
|
||||
for _, cmd := range cmds {
|
||||
if cmd.Type == token.SET && cmd.Options == "Shell" || cmd.Type == token.ENV {
|
||||
if cmd.Type == token.SET && cmd.Options == shellSetting || cmd.Type == token.ENV {
|
||||
err := Execute(cmd, &v)
|
||||
if err != nil {
|
||||
return []error{err}
|
||||
@@ -39,7 +39,7 @@ func Evaluate(ctx context.Context, tape string, out io.Writer, opts ...Evaluator
|
||||
}
|
||||
|
||||
// Start things up
|
||||
if err := v.Start(); err != nil {
|
||||
if err := v.Start(ctx); err != nil {
|
||||
return []error{err}
|
||||
}
|
||||
defer func() { _ = v.close() }()
|
||||
@@ -56,7 +56,7 @@ func Evaluate(ctx context.Context, tape string, out io.Writer, opts ...Evaluator
|
||||
for i, cmd := range cmds {
|
||||
if cmd.Type == token.SET || cmd.Type == token.OUTPUT || cmd.Type == token.REQUIRE {
|
||||
_, _ = fmt.Fprintln(out, Highlight(cmd, false))
|
||||
if cmd.Options != "Shell" {
|
||||
if cmd.Options != shellSetting {
|
||||
err := Execute(cmd, &v)
|
||||
if err != nil {
|
||||
return []error{err}
|
||||
@@ -111,7 +111,7 @@ func Evaluate(ctx context.Context, tape string, out io.Writer, opts ...Evaluator
|
||||
}
|
||||
|
||||
// Begin recording frames as we are now in a recording state.
|
||||
ctx, cancel := context.WithCancel(ctx) //nolint:gosec
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
ch := v.Record(ctx)
|
||||
|
||||
// Clean up temporary files at the end.
|
||||
@@ -182,7 +182,7 @@ func Evaluate(ctx context.Context, tape string, out io.Writer, opts ...Evaluator
|
||||
}
|
||||
|
||||
teardown()
|
||||
if err := v.Render(); err != nil {
|
||||
if err := v.Render(ctx); err != nil {
|
||||
return []error{err}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/charmbracelet/vhs
|
||||
|
||||
go 1.25.8
|
||||
go 1.25.12
|
||||
|
||||
require (
|
||||
github.com/agnivade/levenshtein v1.2.1
|
||||
@@ -21,8 +21,8 @@ require (
|
||||
github.com/muesli/roff v0.1.0
|
||||
github.com/muesli/termenv v0.16.0
|
||||
github.com/spf13/cobra v1.10.2
|
||||
golang.org/x/crypto v0.49.0
|
||||
golang.org/x/term v0.41.0
|
||||
golang.org/x/crypto v0.52.0
|
||||
golang.org/x/term v0.43.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -64,11 +64,11 @@ require (
|
||||
github.com/ysmood/got v0.40.0 // indirect
|
||||
github.com/ysmood/gson v0.7.3 // indirect
|
||||
github.com/ysmood/leakless v0.9.0 // indirect
|
||||
github.com/yuin/goldmark v1.7.13 // indirect
|
||||
github.com/yuin/goldmark v1.7.17 // indirect
|
||||
github.com/yuin/goldmark-emoji v1.0.6 // indirect
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
||||
golang.org/x/net v0.51.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
golang.org/x/sys v0.42.0 // indirect
|
||||
golang.org/x/text v0.35.0 // indirect
|
||||
golang.org/x/net v0.54.0 // indirect
|
||||
golang.org/x/sync v0.21.0 // indirect
|
||||
golang.org/x/sys v0.45.0 // indirect
|
||||
golang.org/x/text v0.39.0 // indirect
|
||||
)
|
||||
|
||||
@@ -137,27 +137,27 @@ github.com/ysmood/gson v0.7.3 h1:QFkWbTH8MxyUTKPkVWAENJhxqdBa4lYTQWqZCiLG6kE=
|
||||
github.com/ysmood/gson v0.7.3/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg=
|
||||
github.com/ysmood/leakless v0.9.0 h1:qxCG5VirSBvmi3uynXFkcnLMzkphdh3xx5FtrORwDCU=
|
||||
github.com/ysmood/leakless v0.9.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ=
|
||||
github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA=
|
||||
github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
||||
github.com/yuin/goldmark v1.7.17 h1:p36OVWwRb246iHxA/U4p8OPEpOTESm4n+g+8t0EE5uA=
|
||||
github.com/yuin/goldmark v1.7.17/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
||||
github.com/yuin/goldmark-emoji v1.0.6 h1:QWfF2FYaXwL74tfGOW5izeiZepUDroDJfWubQI9HTHs=
|
||||
github.com/yuin/goldmark-emoji v1.0.6/go.mod h1:ukxJDKFpdFb5x0a5HqbdlcKtebh086iJpI31LTKmWuA=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
|
||||
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
|
||||
golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988=
|
||||
golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
|
||||
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w=
|
||||
golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ=
|
||||
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
|
||||
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
|
||||
golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
|
||||
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
|
||||
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
|
||||
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
|
||||
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4=
|
||||
golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk=
|
||||
golang.org/x/text v0.39.0 h1:UbZz4pLOvn600D6Oh6GGEI6VAmndrEBLv8/6BEXzyus=
|
||||
golang.org/x/text v0.39.0/go.mod h1:3UwRclnC2g0TU9x8PZiyfOajCd1zaUNHF9cvqcQZ+ZM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -297,8 +297,8 @@ func init() {
|
||||
var versionRegex = regexp.MustCompile(`\d+\.\d+\.\d+`)
|
||||
|
||||
// getVersion returns the parsed version of a program.
|
||||
func getVersion(program string) *version.Version {
|
||||
cmd := exec.Command(program, "--version")
|
||||
func getVersion(ctx context.Context, program string) *version.Version {
|
||||
cmd := exec.CommandContext(ctx, program, "--version")
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil
|
||||
@@ -323,7 +323,7 @@ func ensureDependencies() error {
|
||||
return fmt.Errorf("%v is not installed", defaultShell)
|
||||
}
|
||||
|
||||
ttydVersion := getVersion("ttyd")
|
||||
ttydVersion := getVersion(context.Background(), "ttyd")
|
||||
if ttydVersion == nil || ttydVersion.LessThan(ttydMinVersion) {
|
||||
return fmt.Errorf("ttyd version (%s) is out of date, VHS requires %s\n%s",
|
||||
ttydVersion,
|
||||
|
||||
@@ -69,8 +69,8 @@ var EscapeSequences = map[string]string{
|
||||
// vhs record > file.tape
|
||||
//
|
||||
//nolint:wrapcheck
|
||||
func Record(_ *cobra.Command, _ []string) error {
|
||||
command := exec.Command(shell)
|
||||
func Record(cmd *cobra.Command, _ []string) error {
|
||||
command := exec.CommandContext(cmd.Context(), shell)
|
||||
|
||||
command.Env = append(os.Environ(), "VHS_RECORD=true")
|
||||
|
||||
|
||||
+4
-2
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -50,7 +51,7 @@ func (opts *ScreenshotOptions) enableFrameCapture(path string) {
|
||||
}
|
||||
|
||||
// MakeScreenshots generates screenshots by given ScreenshotOptions.
|
||||
func MakeScreenshots(opts ScreenshotOptions) []*exec.Cmd {
|
||||
func MakeScreenshots(ctx context.Context, opts ScreenshotOptions) []*exec.Cmd {
|
||||
cmds := []*exec.Cmd{} //nolint:prealloc
|
||||
|
||||
for path, frame := range opts.screenshots {
|
||||
@@ -59,7 +60,8 @@ func MakeScreenshots(opts ScreenshotOptions) []*exec.Cmd {
|
||||
|
||||
args := opts.buildFFopts(path, textStream, cursorStream)
|
||||
|
||||
cmds = append(cmds, exec.Command(
|
||||
cmds = append(cmds, exec.CommandContext(
|
||||
ctx,
|
||||
"ffmpeg",
|
||||
args...,
|
||||
))
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// Package token provides the token types and structures for the VHS Tape
|
||||
// language.
|
||||
//
|
||||
//nolint:revive
|
||||
package token
|
||||
|
||||
import (
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
@@ -24,7 +25,7 @@ func randomPort() int {
|
||||
}
|
||||
|
||||
// buildTtyCmd builds the ttyd exec.Command on the given port.
|
||||
func buildTtyCmd(port int, shell Shell) *exec.Cmd {
|
||||
func buildTtyCmd(ctx context.Context, port int, shell Shell) *exec.Cmd {
|
||||
args := []string{ //nolint:prealloc
|
||||
fmt.Sprintf("--port=%d", port),
|
||||
"--interface", "127.0.0.1",
|
||||
@@ -38,7 +39,7 @@ func buildTtyCmd(port int, shell Shell) *exec.Cmd {
|
||||
|
||||
args = append(args, shell.Command...)
|
||||
|
||||
cmd := exec.Command("ttyd", args...)
|
||||
cmd := exec.CommandContext(ctx, "ttyd", args...)
|
||||
if shell.Env != nil {
|
||||
cmd.Env = append(shell.Env, os.Environ()...)
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ func New() VHS {
|
||||
}
|
||||
|
||||
// Start starts ttyd, browser and everything else needed to create the gif.
|
||||
func (vhs *VHS) Start() error {
|
||||
func (vhs *VHS) Start(ctx context.Context) error {
|
||||
vhs.mutex.Lock()
|
||||
defer vhs.mutex.Unlock()
|
||||
|
||||
@@ -131,7 +131,7 @@ func (vhs *VHS) Start() error {
|
||||
}
|
||||
|
||||
port := randomPort()
|
||||
vhs.tty = buildTtyCmd(port, vhs.Options.Shell)
|
||||
vhs.tty = buildTtyCmd(ctx, port, vhs.Options.Shell)
|
||||
if err := vhs.tty.Start(); err != nil {
|
||||
return fmt.Errorf("could not start tty: %w", err)
|
||||
}
|
||||
@@ -220,7 +220,7 @@ func (vhs *VHS) Cleanup() error {
|
||||
}
|
||||
|
||||
// Render starts rendering the individual frames into a video.
|
||||
func (vhs *VHS) Render() error {
|
||||
func (vhs *VHS) Render(ctx context.Context) error {
|
||||
// Apply Loop Offset by modifying frame sequence
|
||||
if err := vhs.ApplyLoopOffset(); err != nil {
|
||||
return err
|
||||
@@ -228,10 +228,10 @@ func (vhs *VHS) Render() error {
|
||||
|
||||
// Generate the video(s) with the frames.
|
||||
var cmds []*exec.Cmd //nolint:prealloc
|
||||
cmds = append(cmds, MakeGIF(vhs.Options.Video))
|
||||
cmds = append(cmds, MakeMP4(vhs.Options.Video))
|
||||
cmds = append(cmds, MakeWebM(vhs.Options.Video))
|
||||
cmds = append(cmds, MakeScreenshots(vhs.Options.Screenshot)...)
|
||||
cmds = append(cmds, MakeGIF(ctx, vhs.Options.Video))
|
||||
cmds = append(cmds, MakeMP4(ctx, vhs.Options.Video))
|
||||
cmds = append(cmds, MakeWebM(ctx, vhs.Options.Video))
|
||||
cmds = append(cmds, MakeScreenshots(ctx, vhs.Options.Screenshot)...)
|
||||
|
||||
for _, cmd := range cmds {
|
||||
if cmd == nil {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
@@ -81,7 +82,7 @@ func marginFillIsColor(marginFill string) bool {
|
||||
}
|
||||
|
||||
// makeMedia takes a list of images (as frames) and converts them to a GIF/WebM/MP4.
|
||||
func makeMedia(opts VideoOptions, targetFile string) *exec.Cmd {
|
||||
func makeMedia(ctx context.Context, opts VideoOptions, targetFile string) *exec.Cmd {
|
||||
if targetFile == "" {
|
||||
return nil
|
||||
}
|
||||
@@ -90,7 +91,8 @@ func makeMedia(opts VideoOptions, targetFile string) *exec.Cmd {
|
||||
ensureDir(targetFile)
|
||||
|
||||
//nolint:gosec
|
||||
return exec.Command(
|
||||
return exec.CommandContext(
|
||||
ctx,
|
||||
"ffmpeg",
|
||||
buildFFopts(opts, targetFile)...,
|
||||
)
|
||||
@@ -153,16 +155,16 @@ func buildFFopts(opts VideoOptions, targetFile string) []string {
|
||||
}
|
||||
|
||||
// MakeGIF takes a list of images (as frames) and converts them to a GIF.
|
||||
func MakeGIF(opts VideoOptions) *exec.Cmd {
|
||||
return makeMedia(opts, opts.Output.GIF)
|
||||
func MakeGIF(ctx context.Context, opts VideoOptions) *exec.Cmd {
|
||||
return makeMedia(ctx, opts, opts.Output.GIF)
|
||||
}
|
||||
|
||||
// MakeWebM takes a list of images (as frames) and converts them to a WebM.
|
||||
func MakeWebM(opts VideoOptions) *exec.Cmd {
|
||||
return makeMedia(opts, opts.Output.WebM)
|
||||
func MakeWebM(ctx context.Context, opts VideoOptions) *exec.Cmd {
|
||||
return makeMedia(ctx, opts, opts.Output.WebM)
|
||||
}
|
||||
|
||||
// MakeMP4 takes a list of images (as frames) and converts them to an MP4.
|
||||
func MakeMP4(opts VideoOptions) *exec.Cmd {
|
||||
return makeMedia(opts, opts.Output.MP4)
|
||||
func MakeMP4(ctx context.Context, opts VideoOptions) *exec.Cmd {
|
||||
return makeMedia(ctx, opts, opts.Output.MP4)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user