131 lines
5.0 KiB
Go
131 lines
5.0 KiB
Go
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
|
|
}
|