package main import ( "embed" "encoding/json" "io/fs" "os" "path/filepath" "time" "github.com/adrg/xdg" ) const defaultOutputFilename = "freeze.png" // Config is the configuration options for a screenshot. type Config struct { Input string `json:",omitempty" arg:"" help:"Code to screenshot." optional:""` // Window Background string `json:"background" help:"Apply a background fill." short:"b" placeholder:"#171717" group:"Window"` Margin []float64 `json:"margin" help:"Apply margin to the window." short:"m" placeholder:"0" group:"Window"` Padding []float64 `json:"padding" help:"Apply padding to the code." short:"p" placeholder:"0" group:"Window"` Window bool `json:"window" help:"Display window controls." group:"Window"` Width float64 `json:"width" help:"Width of terminal window." short:"W" group:"Window"` Height float64 `json:"height" help:"Height of terminal window." short:"H" group:"Window"` // Settings Version bool `json:"version" help:"Display Freeze's version." short:"v" group:"Settings"` Config string `json:"config,omitempty" help:"Base configuration file or template." short:"c" group:"Settings" default:"default" placeholder:"base"` Interactive bool `hidden:"" json:",omitempty" help:"Use an interactive form for configuration options." short:"i" group:"Settings"` Language string `json:"language,omitempty" help:"Language of code file." short:"l" group:"Settings" placeholder:"go"` Theme string `json:"theme" help:"Theme to use for syntax highlighting." short:"t" group:"Settings" placeholder:"charm"` Wrap int `json:"wrap" help:"Wrap lines at a specific width." short:"w" group:"Settings" default:"0" placeholder:"80"` Output string `json:"output,omitempty" help:"Output location for {{.svg}}, {{.png}}, or {{.webp}}." short:"o" group:"Settings" default:"" placeholder:"freeze.svg"` Execute string `json:"-" help:"Capture output of command execution." short:"x" group:"Settings" default:""` ExecuteTimeout time.Duration `json:"-" help:"Execution timeout." group:"Settings" default:"10s" prefix:"execute." name:"timeout" hidden:""` // Decoration Border Border `json:"border" embed:"" prefix:"border." group:"Border"` Shadow Shadow `json:"shadow" embed:"" prefix:"shadow." help:"add a shadow to the window" short:"s" group:"Shadow"` // Font Font Font `json:"font" embed:"" prefix:"font." group:"Font"` // Line LineHeight float64 `json:"line_height" help:"Line height relative to font size." group:"Line" placeholder:"1.2"` Lines []int `json:"-" help:"Lines to capture (start,end)." group:"Line" placeholder:"0,-1" value:"0,-1"` ShowLineNumbers bool `json:"show_line_numbers" help:"" group:"Line" placeholder:"false"` } // Shadow is the configuration options for a drop shadow. type Shadow struct { Blur float64 `json:"blur" help:"Shadow Gaussian Blur." placeholder:"0"` X float64 `json:"x" help:"Shadow offset {{x}} coordinate." placeholder:"0"` Y float64 `json:"y" help:"Shadow offset {{y}} coordinate." placeholder:"0"` } // Border is the configuration options for a window border. type Border struct { Radius float64 `json:"radius" help:"Corner radius of window." short:"r" placeholder:"0"` Width float64 `json:"width" help:"Border width thickness." placeholder:"1"` Color string `json:"color" help:"Border color." placeholder:"#000"` } // Font is the configuration options for a font. type Font struct { Family string `json:"family" help:"Font family to use for code." placeholder:"monospace"` File string `json:"file" help:"Font file to embed." placeholder:"monospace.ttf"` Size float64 `json:"size" help:"Font size to use for code." placeholder:"14"` Ligatures bool `json:"ligatures" help:"Use ligatures in the font." placeholder:"true" value:"true" negatable:""` } //go:embed configurations/* var configs embed.FS func expandPadding(p []float64, scale float64) []float64 { switch len(p) { case 1: return []float64{p[top] * scale, p[top] * scale, p[top] * scale, p[top] * scale} case 2: return []float64{p[top] * scale, p[right] * scale, p[top] * scale, p[right] * scale} case 4: return []float64{p[top] * scale, p[right] * scale, p[bottom] * scale, p[left] * scale} default: return []float64{0, 0, 0, 0} } } var expandMargin = expandPadding type side int const ( top side = 0 right side = 1 bottom side = 2 left side = 3 ) var userConfigPath = filepath.Join(xdg.ConfigHome, "freeze", "user.json") func loadUserConfig() (fs.File, error) { return os.Open(userConfigPath) //nolint: wrapcheck } func saveUserConfig(config Config) error { config.Input = "" config.Output = "" config.Interactive = false err := os.MkdirAll(filepath.Dir(userConfigPath), os.ModePerm) //nolint:gosec if err != nil { return err //nolint: wrapcheck } f, err := os.Create(userConfigPath) if err != nil { return err //nolint: wrapcheck } b, err := json.Marshal(config) if err != nil { return err //nolint: wrapcheck } _, err = f.Write(b) printFilenameOutput(userConfigPath) return err //nolint: wrapcheck }