Skip to content

Instantly share code, notes, and snippets.

@EarlGray
Created February 21, 2024 22:16
Show Gist options
  • Save EarlGray/2f1e7e71cc8ad3887f958e9c90079ead to your computer and use it in GitHub Desktop.
Save EarlGray/2f1e7e71cc8ad3887f958e9c90079ead to your computer and use it in GitHub Desktop.
package main
import (
"flag"
"fmt"
"io"
"log"
"os"
"os/exec"
"path/filepath"
"syscall"
"github.com/kyoh86/xdg"
yaml "gopkg.in/yaml.v3"
)
const AlacrittyBinary = "alacritty"
const ConfigPathEnvVar = "ALACRITTY_CONFIG"
var (
AlacrittyConfigPath = ""
// flags:
execFlag = flag.String("e", "", "command to execute in Alacritty")
profileFlag = flag.String("p", "", "a yml profile in ~/.config/alacritty/profiles/")
ctrlFlag = flag.String("c", "", "control already running alcrtty")
)
func copyFile(srcpath, dstpath string) error {
r, err := os.Open(srcpath)
if err != nil {
return err
}
defer r.Close()
w, err := os.Create(dstpath)
if err != nil {
return err
}
defer func() {
errw := w.Close()
if errw != nil && err == nil {
err = errw
}
}()
_, err = io.Copy(w, r)
return err
}
type ConfigData = map[string]interface{}
type Config struct {
sessionPath string
}
func NewConfig() (*Config, error) {
sessionPath, ok := os.LookupEnv("ALACRITTY_CONFIG")
if ok {
return &Config{sessionPath: sessionPath}, nil
}
// else, create a new one:
sessionDir, err := os.MkdirTemp("", "alcrtty")
if err != nil {
return nil, err
}
sessionPath = filepath.Join(sessionDir, "conf.yml")
err = os.WriteFile(sessionPath, []byte{}, 0644)
return &Config{
sessionPath: sessionPath,
}, err
}
func (c *Config) Update(update func(*ConfigData) *ConfigData) error {
data := new(map[string]interface{})
r, err := os.ReadFile(c.sessionPath)
if err != nil {
return err
}
err = yaml.Unmarshal(r, data)
if err != nil {
return err
}
data = update(data)
w, err := os.Create(c.sessionPath)
if err != nil {
return err
}
enc := yaml.NewEncoder(w)
defer enc.Close()
err = enc.Encode(data)
return err
}
func (c *Config) CopyFromProfile(profile string) error {
sessionFile := profile + ".yml"
profilePath := filepath.Join(AlacrittyConfigPath, "profiles", sessionFile)
log.Printf("profile path = %v", profilePath)
log.Printf("session path = %v", c.sessionPath)
_, err := os.Stat(profilePath)
if err != nil {
fmt.Fprintf(os.Stderr, "No such profile %v, falling back to default", profilePath)
return nil
}
err = copyFile(profilePath, c.sessionPath)
return err
}
func (config *Config) Run() {
exepath, err := exec.LookPath(AlacrittyBinary)
if err != nil {
log.Fatalf("Alacritty binary %q not found", AlacrittyBinary)
}
args := []string{
AlacrittyBinary,
"--config-file=" + config.sessionPath,
}
args = append(args, flag.Args()...)
// must be last for Alacritty:
if *execFlag != "" {
args = append(args, "-e", *execFlag)
}
env := os.Environ()
env = append(env, ConfigPathEnvVar+"="+config.sessionPath)
log.Printf("Run: %v %v", exepath, args)
err = syscall.Exec(exepath, args, env)
log.Fatalf("exec: %v", err)
}
func run() {
// Run:
config, err := NewConfig()
if err != nil {
fmt.Fprintf(os.Stderr, "failed to create a temporary directory: %v", err)
}
if *profileFlag != "" {
err = config.CopyFromProfile(*profileFlag)
if err != nil {
log.Fatalf("Failed to copy profile: %v", *profileFlag)
}
}
config.Run()
}
func cmd(command string) {
switch command {
default:
fmt.Fprintf(os.Stderr, "No known commands yet :(\n")
}
}
func main() {
AlacrittyConfigPath = filepath.Join(xdg.ConfigHome(), "alacritty")
flag.Parse()
exename := filepath.Base(os.Args[0])
log.Printf("Called as %q\n", exename)
if *ctrlFlag != "" {
cmd(*ctrlFlag)
//} else if exename == "alcrtty-ctl" {
// cmd(flag.Args[0])
} else {
run()
}
}
// vim: set ts=4 noet :
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment