package main import ( "code.icb4dc0.de/prskr/go-pwgen" "flag" "fmt" "log" "os" "strings" ) // although there might be terminals where it's less, let's be pessimistic const tabWidth = 8 var ( length uint count int letters uint lowercase uint uppercase uint digits uint specials uint specialsAlphabet string ) func main() { flags := flag.NewFlagSet("pwgen", flag.ExitOnError) flags.IntVar(&count, "count", 20, "Number of passwords to generate") flags.UintVar(&length, "length", 20, "Length of each password to generate") flags.UintVar(&letters, "letters", 0, "Number of letters to include at least") flags.UintVar(&lowercase, "lowercase", 3, "Number of lowercase characters to include at least") flags.UintVar(&uppercase, "uppercase", 3, "Number of uppercase characters to include at least") flags.UintVar(&digits, "digits", 3, "Number of digits to include at least") flags.UintVar(&specials, "specials", 0, "Number of special characters to include at least") flags.StringVar(&specialsAlphabet, "specials-alphabet", pwgen.DefaultSpecialsAlphabet, "Special characters to include as special characters") if err := flags.Parse(os.Args[1:]); err != nil { log.Fatalf("Failed to parse arguments: %v", err) } terminalWidth := getWidth() passwordsPerRow := int(terminalWidth / (length + tabWidth)) builder := strings.Builder{} for i := 0; i < count; i += passwordsPerRow { for j := 0; j < passwordsPerRow && i+j < count; j++ { pw, err := pwgen.Generate( pwgen.WithLength(length), pwgen.WithLetters(letters), pwgen.WithLowercase(lowercase), pwgen.WithUppercase(uppercase), pwgen.WithDigits(digits), pwgen.WithSpecials(specials), pwgen.WithSpecialsAlphabet(specialsAlphabet), ) if err != nil { log.Fatalf("Error occurred generating password: %v", err) } builder.WriteString(pw) builder.WriteRune('\t') } fmt.Println(strings.TrimSuffix(builder.String(), "\t")) builder.Reset() } }