MVP
This commit is contained in:
commit
d5762330da
23 changed files with 718 additions and 0 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
use flake
|
||||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
.direnv
|
||||||
|
bin
|
||||||
|
result
|
||||||
|
data
|
||||||
|
output
|
||||||
58
cmd/root.go
Normal file
58
cmd/root.go
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"specCon18/wand-templater/render"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CLI flag variables
|
||||||
|
var (
|
||||||
|
modName string
|
||||||
|
packageName string
|
||||||
|
programVersion string
|
||||||
|
programDesc string
|
||||||
|
outputDir string // NEW: output directory flag
|
||||||
|
)
|
||||||
|
|
||||||
|
// rootCmd renders templates using CLI flags
|
||||||
|
var rootCmd = &cobra.Command{
|
||||||
|
Use: "wand-templater",
|
||||||
|
Short: "A tool to generate a go project template for building a terminal application with bubbletea + cobra + viper + log + mango",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
// Fill ProgramData from CLI input
|
||||||
|
data := render.ProgramData{
|
||||||
|
ModName: modName,
|
||||||
|
PackageName: packageName,
|
||||||
|
ProgramVersion: programVersion,
|
||||||
|
ProgramDesc: programDesc,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render templates to the specified output directory
|
||||||
|
if err := render.RenderTemplates(data, outputDir); err != nil {
|
||||||
|
log.Fatalf("rendering failed: %v", err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute starts the CLI application
|
||||||
|
func Execute() {
|
||||||
|
cobra.CheckErr(rootCmd.Execute())
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Register flags
|
||||||
|
rootCmd.Flags().StringVar(&modName, "mod-name", "", "Module name (e.g. github.com/user/app)")
|
||||||
|
rootCmd.Flags().StringVar(&packageName, "package-name", "", "Package name")
|
||||||
|
rootCmd.Flags().StringVar(&programVersion, "program-version", "", "Program version")
|
||||||
|
rootCmd.Flags().StringVar(&programDesc, "program-desc", "", "Program description")
|
||||||
|
rootCmd.Flags().StringVarP(&outputDir, "output", "o", "output", "Output directory for rendered files")
|
||||||
|
|
||||||
|
// Mark required
|
||||||
|
rootCmd.MarkFlagRequired("mod-name")
|
||||||
|
rootCmd.MarkFlagRequired("package-name")
|
||||||
|
rootCmd.MarkFlagRequired("program-version")
|
||||||
|
rootCmd.MarkFlagRequired("program-desc")
|
||||||
|
}
|
||||||
|
|
||||||
48
cmd/tui.go
Normal file
48
cmd/tui.go
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/charmbracelet/huh"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"specCon18/wand-templater/render"
|
||||||
|
)
|
||||||
|
|
||||||
|
// tuiCmd renders templates interactively via a form
|
||||||
|
var tuiCmd = &cobra.Command{
|
||||||
|
Use: "tui",
|
||||||
|
Short: "an interactive TUI for generating a go module template for terminal applications using bubbletea + cobra + viper + log + mango",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
var data render.ProgramData
|
||||||
|
|
||||||
|
// Build the input form
|
||||||
|
form := huh.NewForm(
|
||||||
|
huh.NewGroup(
|
||||||
|
huh.NewInput().Title("Module Name").Placeholder("e.g. github.com/you/project").Value(&data.ModName),
|
||||||
|
huh.NewInput().Title("Package Name").Placeholder("e.g. myapp").Value(&data.PackageName),
|
||||||
|
huh.NewInput().Title("Program Version").Placeholder("e.g. 1.0.0").Value(&data.ProgramVersion),
|
||||||
|
huh.NewInput().Title("Program Description").Placeholder("Describe your program").Value(&data.ProgramDesc),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Run the form and exit on cancel
|
||||||
|
if err := form.Run(); err != nil {
|
||||||
|
log.Fatalf("form cancelled or failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve --output flag value
|
||||||
|
out, _ := cmd.Flags().GetString("output")
|
||||||
|
|
||||||
|
// Render templates with user input
|
||||||
|
if err := render.RenderTemplates(data, out); err != nil {
|
||||||
|
log.Fatalf("rendering failed: %v", err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Allow output dir override
|
||||||
|
tuiCmd.Flags().StringP("output", "o", "output", "Output directory for rendered files")
|
||||||
|
rootCmd.AddCommand(tuiCmd)
|
||||||
|
}
|
||||||
|
|
||||||
40
flake.lock
generated
Normal file
40
flake.lock
generated
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-schemas": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1721999734,
|
||||||
|
"narHash": "sha256-G5CxYeJVm4lcEtaO87LKzOsVnWeTcHGKbKxNamNWgOw=",
|
||||||
|
"rev": "0a5c42297d870156d9c57d8f99e476b738dcd982",
|
||||||
|
"revCount": 75,
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://api.flakehub.com/f/pinned/DeterminateSystems/flake-schemas/0.1.5/0190ef2f-61e0-794b-ba14-e82f225e55e6/source.tar.gz"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://flakehub.com/f/DeterminateSystems/flake-schemas/%2A"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1752866191,
|
||||||
|
"narHash": "sha256-NV4S2Lf2hYmZQ3Qf4t/YyyBaJNuxLPyjzvDma0zPp/M=",
|
||||||
|
"rev": "f01fe91b0108a7aff99c99f2e9abbc45db0adc2a",
|
||||||
|
"revCount": 806668,
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.2505.806668%2Brev-f01fe91b0108a7aff99c99f2e9abbc45db0adc2a/0198265b-7f79-72d2-af6f-40a40431be71/source.tar.gz"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://flakehub.com/f/NixOS/nixpkgs/%2A"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-schemas": "flake-schemas",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
74
flake.nix
Normal file
74
flake.nix
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
# This flake was initially generated by fh, the CLI for FlakeHub (version 0.1.22)
|
||||||
|
{
|
||||||
|
# A helpful description of your flake
|
||||||
|
description = "a tool for managing Wand template repos";
|
||||||
|
|
||||||
|
# Flake inputs
|
||||||
|
inputs = {
|
||||||
|
flake-schemas.url = "https://flakehub.com/f/DeterminateSystems/flake-schemas/*";
|
||||||
|
|
||||||
|
nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/*";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Flake outputs that other flakes can use
|
||||||
|
outputs =
|
||||||
|
{
|
||||||
|
self,
|
||||||
|
flake-schemas,
|
||||||
|
nixpkgs,
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
# Helpers for producing system-specific outputs
|
||||||
|
supportedSystems = [ "x86_64-linux" ];
|
||||||
|
forEachSupportedSystem =
|
||||||
|
f:
|
||||||
|
nixpkgs.lib.genAttrs supportedSystems (
|
||||||
|
system:
|
||||||
|
f {
|
||||||
|
inherit (nixpkgs) lib;
|
||||||
|
pkgs = import nixpkgs { inherit system; };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# Schemas tell Nix about the structure of your flake's outputs
|
||||||
|
schemas = flake-schemas.schemas;
|
||||||
|
packages = forEachSupportedSystem (
|
||||||
|
{ pkgs, lib }:
|
||||||
|
{
|
||||||
|
default = pkgs.callPackage (
|
||||||
|
{ buildGoModule }:
|
||||||
|
buildGoModule {
|
||||||
|
pname = "wand-templater";
|
||||||
|
version = "0.0.1";
|
||||||
|
src = builtins.path {
|
||||||
|
name = "source";
|
||||||
|
path = ./.;
|
||||||
|
};
|
||||||
|
vendorHash = "sha256-SQHzChRwEx8VYJwXcZXTMDgILrhhRvGqrdQ1k3lFWgk=";
|
||||||
|
}
|
||||||
|
) { };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
# Development environments
|
||||||
|
devShells = forEachSupportedSystem (
|
||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
# Pinned packages available in the environment
|
||||||
|
packages = with pkgs; [
|
||||||
|
just
|
||||||
|
gcc
|
||||||
|
go_1_23
|
||||||
|
gopls
|
||||||
|
nixpkgs-fmt
|
||||||
|
];
|
||||||
|
env = {
|
||||||
|
CGO_ENABLED = "1";
|
||||||
|
CC = "gcc";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
39
go.mod
Normal file
39
go.mod
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
module specCon18/wand-templater
|
||||||
|
|
||||||
|
go 1.23.11
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/charmbracelet/huh v0.7.0
|
||||||
|
github.com/spf13/cobra v1.9.1
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/atotto/clipboard v0.1.4 // indirect
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
|
github.com/catppuccin/go v0.3.0 // indirect
|
||||||
|
github.com/charmbracelet/bubbles v0.21.0 // indirect
|
||||||
|
github.com/charmbracelet/bubbletea v1.3.4 // indirect
|
||||||
|
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
|
||||||
|
github.com/charmbracelet/lipgloss v1.1.0 // indirect
|
||||||
|
github.com/charmbracelet/x/ansi v0.8.0 // indirect
|
||||||
|
github.com/charmbracelet/x/cellbuf v0.0.13 // indirect
|
||||||
|
github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 // indirect
|
||||||
|
github.com/charmbracelet/x/term v0.2.1 // indirect
|
||||||
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/mattn/go-localereader v0.0.1 // indirect
|
||||||
|
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||||
|
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
|
||||||
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||||
|
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||||
|
github.com/muesli/termenv v0.16.0 // indirect
|
||||||
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.6 // indirect
|
||||||
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||||
|
golang.org/x/sync v0.12.0 // indirect
|
||||||
|
golang.org/x/sys v0.31.0 // indirect
|
||||||
|
golang.org/x/text v0.23.0 // indirect
|
||||||
|
)
|
||||||
85
go.sum
Normal file
85
go.sum
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
||||||
|
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
||||||
|
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||||
|
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||||
|
github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
|
||||||
|
github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
|
||||||
|
github.com/catppuccin/go v0.3.0 h1:d+0/YicIq+hSTo5oPuRi5kOpqkVA5tAsU6dNhvRu+aY=
|
||||||
|
github.com/catppuccin/go v0.3.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc=
|
||||||
|
github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs=
|
||||||
|
github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg=
|
||||||
|
github.com/charmbracelet/bubbletea v1.3.4 h1:kCg7B+jSCFPLYRA52SDZjr51kG/fMUEoPoZrkaDHyoI=
|
||||||
|
github.com/charmbracelet/bubbletea v1.3.4/go.mod h1:dtcUCyCGEX3g9tosuYiut3MXgY/Jsv9nKVdibKKRRXo=
|
||||||
|
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
|
||||||
|
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk=
|
||||||
|
github.com/charmbracelet/huh v0.7.0 h1:W8S1uyGETgj9Tuda3/JdVkc3x7DBLZYPZc4c+/rnRdc=
|
||||||
|
github.com/charmbracelet/huh v0.7.0/go.mod h1:UGC3DZHlgOKHvHC07a5vHag41zzhpPFj34U92sOmyuk=
|
||||||
|
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
|
||||||
|
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
|
||||||
|
github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE=
|
||||||
|
github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q=
|
||||||
|
github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k=
|
||||||
|
github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
|
||||||
|
github.com/charmbracelet/x/conpty v0.1.0 h1:4zc8KaIcbiL4mghEON8D72agYtSeIgq8FSThSPQIb+U=
|
||||||
|
github.com/charmbracelet/x/conpty v0.1.0/go.mod h1:rMFsDJoDwVmiYM10aD4bH2XiRgwI7NYJtQgl5yskjEQ=
|
||||||
|
github.com/charmbracelet/x/errors v0.0.0-20240508181413-e8d8b6e2de86 h1:JSt3B+U9iqk37QUU2Rvb6DSBYRLtWqFqfxf8l5hOZUA=
|
||||||
|
github.com/charmbracelet/x/errors v0.0.0-20240508181413-e8d8b6e2de86/go.mod h1:2P0UgXMEa6TsToMSuFqKFQR+fZTO9CNGUNokkPatT/0=
|
||||||
|
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ=
|
||||||
|
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
|
||||||
|
github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 h1:qko3AQ4gK1MTS/de7F5hPGx6/k1u0w4TeYmBFwzYVP4=
|
||||||
|
github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0/go.mod h1:pBhA0ybfXv6hDjQUZ7hk1lVxBiUbupdw5R31yPUViVQ=
|
||||||
|
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
|
||||||
|
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
|
||||||
|
github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY=
|
||||||
|
github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo=
|
||||||
|
github.com/charmbracelet/x/xpty v0.1.2 h1:Pqmu4TEJ8KeA9uSkISKMU3f+C1F6OGBn8ABuGlqCbtI=
|
||||||
|
github.com/charmbracelet/x/xpty v0.1.2/go.mod h1:XK2Z0id5rtLWcpeNiMYBccNNBrP2IJnzHI0Lq13Xzq4=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
|
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
|
||||||
|
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
|
||||||
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||||
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
|
||||||
|
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
|
||||||
|
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||||
|
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
|
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
|
||||||
|
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
|
||||||
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
|
||||||
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
||||||
|
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||||
|
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
||||||
|
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
|
||||||
|
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
|
||||||
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||||
|
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||||
|
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||||
|
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||||
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||||
|
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
||||||
|
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
||||||
|
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||||
|
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
|
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.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||||
|
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
|
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||||
|
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
31
justfile
Normal file
31
justfile
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
|
||||||
|
# Set the shell
|
||||||
|
set shell := ["bash", "-cu"]
|
||||||
|
|
||||||
|
# Build the Go project
|
||||||
|
build:
|
||||||
|
go build -o bin/app .
|
||||||
|
|
||||||
|
# Run the Go project
|
||||||
|
run:
|
||||||
|
go run .
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
test:
|
||||||
|
go test ./...
|
||||||
|
|
||||||
|
# Clean build artifacts
|
||||||
|
clean:
|
||||||
|
rm -rf bin
|
||||||
|
|
||||||
|
# Format the code
|
||||||
|
fmt:
|
||||||
|
go fmt ./...
|
||||||
|
|
||||||
|
# Tidy up go.mod/go.sum
|
||||||
|
tidy:
|
||||||
|
go mod tidy
|
||||||
|
|
||||||
|
# Init Go module (optional first step)
|
||||||
|
init name:
|
||||||
|
go mod init {{name}}
|
||||||
10
main.go
Normal file
10
main.go
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"specCon18/wand-templater/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cmd.Execute()
|
||||||
|
}
|
||||||
|
|
||||||
57
render/render.go
Normal file
57
render/render.go
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
package render
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ProgramData holds user-supplied template values
|
||||||
|
type ProgramData struct {
|
||||||
|
ModName string
|
||||||
|
PackageName string
|
||||||
|
ProgramVersion string
|
||||||
|
ProgramDesc string
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenderTemplates renders all .tmpl files from the templates/ directory into outputDir
|
||||||
|
func RenderTemplates(data ProgramData, outputDir string) error {
|
||||||
|
return filepath.Walk("templates", func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if info.IsDir() || !strings.HasSuffix(info.Name(), ".tmpl") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create relative output path (preserving subdirs)
|
||||||
|
relPath, err := filepath.Rel("templates", path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
outputPath := filepath.Join(outputDir, strings.TrimSuffix(relPath, ".tmpl"))
|
||||||
|
|
||||||
|
// Ensure parent directories exist
|
||||||
|
if err := os.MkdirAll(filepath.Dir(outputPath), 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse and execute template
|
||||||
|
tmpl, err := template.ParseFiles(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
outFile, err := os.Create(outputPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer outFile.Close()
|
||||||
|
|
||||||
|
log.Printf("Rendering %s → %s\n", path, outputPath)
|
||||||
|
return tmpl.Execute(outFile, data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
4
templates/README.md.tmpl
Normal file
4
templates/README.md.tmpl
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# {{.PackageName}}
|
||||||
|
|
||||||
|
## TLDR;
|
||||||
|
{{.ProgramDesc}}
|
||||||
28
templates/cmd/root.go.tmpl
Normal file
28
templates/cmd/root.go.tmpl
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"{{.ModName}}/tui"
|
||||||
|
)
|
||||||
|
|
||||||
|
var rootCmd = &cobra.Command{
|
||||||
|
Use: "{{.PackageName}}",
|
||||||
|
Short: "{{.PackageName}}, {{.ProgramDesc}}",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := tui.Run(); err != nil {
|
||||||
|
fmt.Println("Error:", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func Execute() {
|
||||||
|
cobra.CheckErr(rootCmd.Execute())
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootCmd.AddCommand(versionCmd)
|
||||||
|
}
|
||||||
15
templates/cmd/version.go.tmpl
Normal file
15
templates/cmd/version.go.tmpl
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var versionCmd = &cobra.Command{
|
||||||
|
Use: "version",
|
||||||
|
Short: "Print the version number of {{.PackageName}}",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Println("{{.PackageName}} ~ {{.ProgramVersion}}")
|
||||||
|
},
|
||||||
|
}
|
||||||
19
templates/config/config.go.tmpl
Normal file
19
templates/config/config.go.tmpl
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Init() {
|
||||||
|
viper.SetConfigName("config") // config.yaml
|
||||||
|
viper.SetConfigType("yaml")
|
||||||
|
viper.AddConfigPath(".")
|
||||||
|
|
||||||
|
err := viper.ReadInConfig()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("No config file found; using defaults.")
|
||||||
|
}
|
||||||
|
|
||||||
|
viper.SetDefault("app.theme", "dark")
|
||||||
|
}
|
||||||
75
templates/flake.nix.tmpl
Normal file
75
templates/flake.nix.tmpl
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
# This flake was initially generated by fh, the CLI for FlakeHub (version 0.1.22)
|
||||||
|
{
|
||||||
|
# A helpful description of your flake
|
||||||
|
description = "{{.ProgramDesc}}";
|
||||||
|
|
||||||
|
# Flake inputs
|
||||||
|
inputs = {
|
||||||
|
flake-schemas.url = "https://flakehub.com/f/DeterminateSystems/flake-schemas/*";
|
||||||
|
|
||||||
|
nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/*";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Flake outputs that other flakes can use
|
||||||
|
outputs =
|
||||||
|
{
|
||||||
|
self,
|
||||||
|
flake-schemas,
|
||||||
|
nixpkgs,
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
# Helpers for producing system-specific outputs
|
||||||
|
supportedSystems = [ "x86_64-linux" ];
|
||||||
|
forEachSupportedSystem =
|
||||||
|
f:
|
||||||
|
nixpkgs.lib.genAttrs supportedSystems (
|
||||||
|
system:
|
||||||
|
f {
|
||||||
|
inherit (nixpkgs) lib;
|
||||||
|
pkgs = import nixpkgs { inherit system; };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# Schemas tell Nix about the structure of your flake's outputs
|
||||||
|
schemas = flake-schemas.schemas;
|
||||||
|
packages = forEachSupportedSystem (
|
||||||
|
{ pkgs, lib }:
|
||||||
|
{
|
||||||
|
default = pkgs.callPackage (
|
||||||
|
{ buildGoModule }:
|
||||||
|
buildGoModule {
|
||||||
|
pname = "{{.PackageName}}";
|
||||||
|
version = "{{.ProgramVersion}}";
|
||||||
|
src = builtins.path {
|
||||||
|
name = "source";
|
||||||
|
path = ./.;
|
||||||
|
};
|
||||||
|
vendorHash = "";
|
||||||
|
}
|
||||||
|
) { };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
# Development environments
|
||||||
|
devShells = forEachSupportedSystem (
|
||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
# Pinned packages available in the environment
|
||||||
|
packages = with pkgs; [
|
||||||
|
just
|
||||||
|
gcc
|
||||||
|
go_1_23
|
||||||
|
nixpkgs-fmt
|
||||||
|
gopls
|
||||||
|
cobra-cli
|
||||||
|
];
|
||||||
|
env = {
|
||||||
|
CGO_ENABLED = "1";
|
||||||
|
CC = "gcc";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
45
templates/go.mod.tmpl
Normal file
45
templates/go.mod.tmpl
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
module {{.ModName}}
|
||||||
|
|
||||||
|
go 1.21
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/charmbracelet/bubbletea v0.25.0
|
||||||
|
github.com/spf13/cobra v1.7.0
|
||||||
|
github.com/spf13/viper v1.17.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
|
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
|
||||||
|
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||||
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||||
|
github.com/magiconair/properties v1.8.7 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.18 // indirect
|
||||||
|
github.com/mattn/go-localereader v0.0.1 // indirect
|
||||||
|
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||||
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
|
github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b // indirect
|
||||||
|
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||||
|
github.com/muesli/reflow v0.3.0 // indirect
|
||||||
|
github.com/muesli/termenv v0.15.2 // indirect
|
||||||
|
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||||
|
github.com/rivo/uniseg v0.2.0 // indirect
|
||||||
|
github.com/sagikazarmark/locafero v0.3.0 // indirect
|
||||||
|
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||||
|
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||||
|
github.com/spf13/afero v1.10.0 // indirect
|
||||||
|
github.com/spf13/cast v1.5.1 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
|
go.uber.org/atomic v1.9.0 // indirect
|
||||||
|
go.uber.org/multierr v1.9.0 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||||
|
golang.org/x/sync v0.3.0 // indirect
|
||||||
|
golang.org/x/sys v0.12.0 // indirect
|
||||||
|
golang.org/x/term v0.6.0 // indirect
|
||||||
|
golang.org/x/text v0.13.0 // indirect
|
||||||
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
||||||
31
templates/justfile.tmpl
Normal file
31
templates/justfile.tmpl
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
|
||||||
|
# Set the shell
|
||||||
|
set shell := ["bash", "-cu"]
|
||||||
|
|
||||||
|
# Build the Go project
|
||||||
|
build:
|
||||||
|
go build -o bin/app .
|
||||||
|
|
||||||
|
# Run the Go project
|
||||||
|
run:
|
||||||
|
go run .
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
test:
|
||||||
|
go test ./...
|
||||||
|
|
||||||
|
# Clean build artifacts
|
||||||
|
clean:
|
||||||
|
rm -rf bin
|
||||||
|
|
||||||
|
# Format the code
|
||||||
|
fmt:
|
||||||
|
go fmt ./...
|
||||||
|
|
||||||
|
# Tidy up go.mod/go.sum
|
||||||
|
tidy:
|
||||||
|
go mod tidy
|
||||||
|
|
||||||
|
# Init Go module (optional first step)
|
||||||
|
init:
|
||||||
|
go mod init
|
||||||
7
templates/main.go.tmpl
Normal file
7
templates/main.go.tmpl
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "{{.ModName}}/cmd"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cmd.Execute()
|
||||||
|
}
|
||||||
11
templates/tui/model.go.tmpl
Normal file
11
templates/tui/model.go.tmpl
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
package tui
|
||||||
|
|
||||||
|
import tea "github.com/charmbracelet/bubbletea"
|
||||||
|
|
||||||
|
type model struct {
|
||||||
|
count int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m model) Init() tea.Cmd {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
10
templates/tui/run.go.tmpl
Normal file
10
templates/tui/run.go.tmpl
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
package tui
|
||||||
|
|
||||||
|
import tea "github.com/charmbracelet/bubbletea"
|
||||||
|
|
||||||
|
func Run() error {
|
||||||
|
p := tea.NewProgram(model{})
|
||||||
|
_, err := p.Run()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
18
templates/tui/update.go.tmpl
Normal file
18
templates/tui/update.go.tmpl
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
package tui
|
||||||
|
|
||||||
|
import tea "github.com/charmbracelet/bubbletea"
|
||||||
|
|
||||||
|
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
switch msg := msg.(type) {
|
||||||
|
case tea.KeyMsg:
|
||||||
|
switch msg.String() {
|
||||||
|
case "q", "ctrl+c":
|
||||||
|
return m, tea.Quit
|
||||||
|
case "up":
|
||||||
|
m.count++
|
||||||
|
case "down":
|
||||||
|
m.count--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
7
templates/tui/view.go.tmpl
Normal file
7
templates/tui/view.go.tmpl
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
package tui
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func (m model) View() string {
|
||||||
|
return "Counter: " + fmt.Sprintf("%d", m.count) + "\n[↑/↓ to change, q to quit]"
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue