Compare commits

...

20 Commits
v0.4.0 ... main

Author SHA1 Message Date
github-actions[bot]
be38fee0ea chore: auto-update Go modules 2025-07-21 00:36:48 +00:00
github-actions[bot]
dd1099f3f2 chore: auto-update Go modules 2025-07-14 00:35:41 +00:00
github-actions[bot]
69d715e4d0 chore: auto-update Go modules 2025-07-07 00:35:16 +00:00
github-actions[bot]
67969d3550 chore: auto-update Go modules 2025-06-30 00:35:02 +00:00
github-actions[bot]
df12de837b chore: auto-update Go modules 2025-06-23 00:34:42 +00:00
bae71b983e bump to 1.0.0 2025-06-19 04:39:43 +01:00
f4ddb45fd2 don't log.Fatal if we can't read version... 2025-06-19 02:21:12 +01:00
cad1585975 add versionFromBuild 2025-06-19 02:12:56 +01:00
4139c4b291 fix regression reading build info 2025-06-19 02:07:25 +01:00
856da5cd04 wrap CLI with fang 2025-06-19 01:53:16 +01:00
a6fb3c69c7 reword 2025-06-18 09:11:15 +01:00
cf93198462 add --start-search/-s flag
upd README
2025-06-18 08:56:05 +01:00
e1875fb894 upd selection prompt image 2025-06-18 06:43:08 +01:00
e1b879f54c change default height to 10
- with startswith filtering its more reasonable
2025-06-18 06:37:06 +01:00
f51302a945 update usage, header + footer. 2025-06-18 06:26:34 +01:00
11fe797f3f upd go.mod to match repository 2025-06-18 06:13:01 +01:00
5b389aa9dc update install link to match new repo name
update taskfile for local builds
2025-06-18 06:08:05 +01:00
bb535f296d fix link 2025-06-18 04:03:13 +01:00
5eccfc939c upd special thanks 2025-06-18 04:02:39 +01:00
00638a6bf4 fix typo 2025-06-18 03:51:58 +01:00
10 changed files with 169 additions and 105 deletions

4
.gitignore vendored
View File

@ -1,4 +1,4 @@
# Generated by ignr-cli: github.com/onyx-and-iris/ignr-cli
# Generated by ignr: github.com/onyx-and-iris/ignr
## Go ##
# If you prefer the allow list template instead of the deny list, see community template:
@ -36,4 +36,4 @@ go.work.sum
# .idea/
# .vscode/
# End of ignr-cli
# End of ignr

View File

@ -2,7 +2,7 @@
![Linux](https://img.shields.io/badge/Linux-FCC624?style=for-the-badge&logo=linux&logoColor=black)
![macOS](https://img.shields.io/badge/mac%20os-000000?style=for-the-badge&logo=macos&logoColor=F0F0F0)
# ignr-cli
# ignr
Simple no-frills .gitignore generator backed by the Github API.
@ -11,7 +11,7 @@ Simple no-frills .gitignore generator backed by the Github API.
## Install
```console
go install github.com/onyx-and-iris/ignr-cli@latest
go install github.com/onyx-and-iris/ignr@latest
```
## Configuration
@ -20,9 +20,10 @@ go install github.com/onyx-and-iris/ignr-cli@latest
- --token/-t: GitHub authentication token
- note, this tool can be used **without** authenticating but rate limiting will be stricter.
- --height/-H: Height of the selection prompt (default 20)
- --height/-H: Height of the selection prompt (default 10)
- --filter/-f: Type of filter to apply to the list of templates (default startswith)
- may be one of (startswith, contains)
- --start-search/-s: Start the prompt in search mode (default false)
*environment variables*
@ -30,8 +31,9 @@ go install github.com/onyx-and-iris/ignr-cli@latest
#!/usr/bin/env bash
export IGNR_TOKEN=<API Token>
export IGNR_HEIGHT=20
export IGNR_HEIGHT=10
export IGNR_FILTER=startswith
export IGNR_START_SEARCH=false
```
## Commands
@ -41,13 +43,14 @@ export IGNR_FILTER=startswith
Trigger the selection prompt.
```console
ignr-cli new
ignr new
```
The prompt filter can be activated by pressing `/`:
Search mode can be activated by pressing `/`:
![Prompt Filter](./img/promptfilter.png)
## Special Thanks
- [Charm](https://github.com/charmbracelet) for their awesome CLI packages.
- [spf13](https://github.com/spf13) for the [cobra](https://github.com/spf13/cobra) and [viper](https://github.com/spf13/viper) packages.
- [Manifold](https://github.com/manifoldco) for the [promptui](https://github.com/manifoldco/promptui) package.

View File

@ -1,7 +1,7 @@
version: '3'
vars:
PROGRAM: ignr-cli
PROGRAM: ignr
SHELL: '{{if eq .OS "Windows_NT"}}powershell{{end}}'
BIN_DIR: bin
VERSION:
@ -12,12 +12,12 @@ vars:
tasks:
default:
desc: Build the ignr-cli project
desc: Build the ignr project
cmds:
- task: build
build:
desc: Build the ignr-cli project
desc: Build the ignr project
deps: [vet]
cmds:
- task: build-windows
@ -35,13 +35,13 @@ tasks:
- go fmt ./...
build-windows:
desc: Build the ignr-cli project for Windows
desc: Build the ignr project for Windows
cmds:
- GOOS=windows GOARCH=amd64 go build -o {{.WINDOWS}} -ldflags="-X main.version={{.VERSION}}"
internal: true
build-linux:
desc: Build the ignr-cli project for Linux
desc: Build the ignr project for Linux
cmds:
- GOOS=linux GOARCH=amd64 go build -o {{.LINUX}} -ldflags="-X main.version={{.VERSION}}"
internal: true

View File

@ -10,13 +10,13 @@ type contextKey string
var clientKey = contextKey("client")
// withClient returns a new context with the GitHub client set.
func withClient(ctx context.Context, client *github.Client) context.Context {
// WithClient returns a new context with the GitHub client set.
func WithClient(ctx context.Context, client *github.Client) context.Context {
return context.WithValue(ctx, clientKey, client)
}
// clientFromContext retrieves the GitHub client from the context.
func clientFromContext(ctx context.Context) (*github.Client, bool) {
// ClientFromContext retrieves the GitHub client from the context.
func ClientFromContext(ctx context.Context) (*github.Client, bool) {
client, ok := ctx.Value(clientKey).(*github.Client)
return client, ok
}

View File

@ -2,13 +2,11 @@ package main
import (
"strings"
"github.com/spf13/viper"
)
// filterFunc returns a function that filters templates based on the specified filter type.
func filterFunc(templates []string) func(input string, index int) bool {
switch viper.GetString("filter") {
func filterFunc(templates []string, filterType string) func(input string, index int) bool {
switch filterType {
case "contains":
return func(input string, index int) bool {
return strings.Contains(strings.ToLower(templates[index]), strings.ToLower(input))

42
go.mod
View File

@ -1,8 +1,9 @@
module github.com/onyx-and-iris/ignr-cli
module github.com/onyx-and-iris/ignr
go 1.24.3
require (
github.com/charmbracelet/fang v0.3.0
github.com/google/go-github/v72 v72.0.0
github.com/manifoldco/promptui v0.9.0
github.com/spf13/cobra v1.9.1
@ -10,21 +11,36 @@ require (
)
require (
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/charmbracelet/colorprofile v0.3.1 // indirect
github.com/charmbracelet/lipgloss/v2 v2.0.0-beta1 // indirect
github.com/charmbracelet/x/ansi v0.9.3 // indirect
github.com/charmbracelet/x/cellbuf v0.0.13 // indirect
github.com/charmbracelet/x/exp/charmtone v0.0.0-20250720010745-3615766e35a0 // indirect
github.com/charmbracelet/x/exp/color v0.0.0-20250720010745-3615766e35a0 // indirect
github.com/charmbracelet/x/term v0.2.1 // indirect
github.com/chzyer/readline v1.5.1 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/sagikazarmark/locafero v0.7.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/mango v0.2.0 // indirect
github.com/muesli/mango-cobra v1.2.0 // indirect
github.com/muesli/mango-pflag v0.1.0 // indirect
github.com/muesli/roff v0.1.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/sagikazarmark/locafero v0.9.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.12.0 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/spf13/afero v1.14.0 // indirect
github.com/spf13/cast v1.9.2 // indirect
github.com/spf13/pflag v1.0.7 // 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/sys v0.31.0 // indirect
golang.org/x/text v0.23.0 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/sys v0.34.0 // indirect
golang.org/x/text v0.27.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

95
go.sum
View File

@ -1,19 +1,41 @@
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
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/charmbracelet/colorprofile v0.3.1 h1:k8dTHMd7fgw4bnFd7jXTLZrSU/CQrKnL3m+AxCzDz40=
github.com/charmbracelet/colorprofile v0.3.1/go.mod h1:/GkGusxNs8VB/RSOh3fu0TJmQ4ICMMPApIIVn0KszZ0=
github.com/charmbracelet/fang v0.3.0 h1:Be6TB+ExS8VWizTQRJgjqbJBudKrmVUet65xmFPGhaA=
github.com/charmbracelet/fang v0.3.0/go.mod h1:b0ZfEXZeBds0I27/wnTfnv2UVigFDXHhrFNwQztfA0M=
github.com/charmbracelet/lipgloss/v2 v2.0.0-beta1 h1:SOylT6+BQzPHEjn15TIzawBPVD0QmhKXbcb3jY0ZIKU=
github.com/charmbracelet/lipgloss/v2 v2.0.0-beta1/go.mod h1:tRlx/Hu0lo/j9viunCN2H+Ze6JrmdjQlXUQvvArgaOc=
github.com/charmbracelet/x/ansi v0.9.3 h1:BXt5DHS/MKF+LjuK4huWrC6NCvHtexww7dMayh6GXd0=
github.com/charmbracelet/x/ansi v0.9.3/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
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/exp/charmtone v0.0.0-20250720010745-3615766e35a0 h1:4MSiRB8CwsNC+9K4dPyvq/zn4koWDFoWz/ntsEZMJAI=
github.com/charmbracelet/x/exp/charmtone v0.0.0-20250720010745-3615766e35a0/go.mod h1:T9jr8CzFpjhFVHjNjKwbAD7KwBNyFnj2pntAO7F2zw0=
github.com/charmbracelet/x/exp/color v0.0.0-20250720010745-3615766e35a0 h1:rxig9Nr2CYHnBMyGygSuaa7CEV6e6tcHkB3cnOG7AEQ=
github.com/charmbracelet/x/exp/color v0.0.0-20250720010745-3615766e35a0/go.mod h1:hk/GyTELmEgX54pBAOHcFvH8Xed53JWo/g8kJXFo/PI=
github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a h1:G99klV19u0QnhiizODirwVksQB91TJKV/UaTnACcG30=
github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM=
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI=
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
@ -27,44 +49,63 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
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/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
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/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/muesli/mango v0.2.0 h1:iNNc0c5VLQ6fsMgAqGQofByNUBH2Q2nEbD6TaI+5yyQ=
github.com/muesli/mango v0.2.0/go.mod h1:5XFpbC8jY5UUv89YQciiXNlbi+iJgt29VDC5xbzrLL4=
github.com/muesli/mango-cobra v1.2.0 h1:DQvjzAM0PMZr85Iv9LIMaYISpTOliMEg+uMFtNbYvWg=
github.com/muesli/mango-cobra v1.2.0/go.mod h1:vMJL54QytZAJhCT13LPVDfkvCUJ5/4jNUKF/8NC2UjA=
github.com/muesli/mango-pflag v0.1.0 h1:UADqbYgpUyRoBja3g6LUL+3LErjpsOwaC9ywvBWe7Sg=
github.com/muesli/mango-pflag v0.1.0/go.mod h1:YEQomTxaCUp8PrbhFh10UfbhbQrM/xJ4i2PB8VTLLW0=
github.com/muesli/roff v0.1.0 h1:YD0lalCotmYuF5HhZliKWlIx7IEhiXeSfq7hNjFqGF8=
github.com/muesli/roff v0.1.0/go.mod h1:pjAHQM9hdUUwm/krAfrLGgJkXJ+YuhtsfZ42kieB2Ig=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
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/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k=
github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA=
github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo=
github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE=
github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
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/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
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=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
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/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
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=
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 10 KiB

51
main.go
View File

@ -3,12 +3,11 @@ package main
import (
"context"
"errors"
"fmt"
"log"
"os"
"runtime/debug"
"strings"
"github.com/charmbracelet/fang"
"github.com/google/go-github/v72/github"
"github.com/spf13/cobra"
"github.com/spf13/viper"
@ -18,9 +17,9 @@ var version string // Version of the CLI, set during build time
// rootCmd represents the base command when called without any subcommands.
var rootCmd = &cobra.Command{
Use: "ignr-cli",
Use: "ignr",
Short: "A command-line interface for generating .gitignore files",
Long: `ignr-cli is a command-line interface for generating .gitignore files.
Long: `ignr is a command-line interface for generating .gitignore files.
It allows users to easily create and manage .gitignore files for various programming languages and frameworks.
You may also list available templates and generate .gitignore files based on those templates.`,
SilenceUsage: true,
@ -31,47 +30,43 @@ You may also list available templates and generate .gitignore files based on tho
} else {
client = github.NewClient(nil).WithAuthToken(viper.GetString("token"))
}
ctx := withClient(context.Background(), client)
cmd.SetContext(ctx)
},
RunE: func(cmd *cobra.Command, _ []string) error {
if cmd.Flags().Lookup("version").Changed {
if version == "" {
info, ok := debug.ReadBuildInfo()
if !ok {
return errors.New("unable to retrieve build information")
}
version = strings.Split(info.Main.Version, "-")[0]
}
fmt.Printf("ignr-cli version: %s\n", version)
return nil
}
return cmd.Help()
cmd.SetContext(WithClient(cmd.Context(), client))
},
}
// init initialises the root command and its flags.
func init() {
rootCmd.PersistentFlags().StringP("token", "t", "", "GitHub authentication token")
rootCmd.PersistentFlags().IntP("height", "H", 20, "Height of the selection prompt")
rootCmd.PersistentFlags().IntP("height", "H", 10, "Height of the selection prompt")
rootCmd.PersistentFlags().
StringP("filter", "f", "startswith", "Type of filter to apply to the list of templates (e.g., 'startswith', 'contains')")
rootCmd.PersistentFlags().BoolP("start-search", "s", false, "Start the prompt in search mode")
rootCmd.Flags().BoolP("version", "v", false, "Print the version of the CLI")
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
viper.SetEnvPrefix("IGNR")
viper.AutomaticEnv()
viper.BindPFlag("token", rootCmd.PersistentFlags().Lookup("token"))
viper.BindPFlag("height", rootCmd.PersistentFlags().Lookup("height"))
viper.BindPFlag("filter", rootCmd.PersistentFlags().Lookup("filter"))
viper.BindPFlag("start-search", rootCmd.PersistentFlags().Lookup("start-search"))
}
// main is the entry point of the application.
// It executes the root command and handles any errors.
func main() {
err := rootCmd.Execute()
if err != nil {
log.Fatal(err)
if err := fang.Execute(context.Background(), rootCmd, fang.WithVersion(versionFromBuild())); err != nil {
os.Exit(1)
}
}
func versionFromBuild() string {
if version == "" {
info, ok := debug.ReadBuildInfo()
if !ok {
return "(unable to read version)"
}
version = strings.Split(info.Main.Version, "-")[0]
}
return version
}

41
new.go
View File

@ -13,7 +13,7 @@ import (
"github.com/spf13/viper"
)
const gitignoreFileName = ".gitignore"
const gitignoreFileName string = ".gitignore"
// newCmd represents the new command.
var newCmd = &cobra.Command{
@ -29,20 +29,30 @@ func init() {
rootCmd.AddCommand(newCmd)
}
type promptConfig struct {
Height int
StartSearch bool
FilterType string
}
// runNewCommand is the handler for the 'new' command.
// It retrieves the selected .gitignore template from GitHub and writes it to the .gitignore file.
func runNewCommand(cmd *cobra.Command, _ []string) error {
height := viper.GetInt("height")
if height <= 0 {
pc := promptConfig{
Height: viper.GetInt("height"),
StartSearch: viper.GetBool("start-search"),
FilterType: viper.GetString("filter"),
}
if pc.Height <= 0 {
return errors.New("height must be a positive integer")
}
client, ok := clientFromContext(cmd.Context())
client, ok := ClientFromContext(cmd.Context())
if !ok {
return errors.New("failed to get GitHub client from context")
}
content, err := runPrompt(client, height)
content, err := runPrompt(client, &pc)
if err != nil {
return fmt.Errorf("error running selection prompt: %w", err)
}
@ -61,13 +71,13 @@ func runNewCommand(cmd *cobra.Command, _ []string) error {
}
// runPrompt is a helper function to run the selection prompt for .gitignore templates.
func runPrompt(client *github.Client, height int) (*github.Gitignore, error) {
func runPrompt(client *github.Client, pc *promptConfig) (*github.Gitignore, error) {
templates, _, err := client.Gitignores.List(context.Background())
if err != nil {
return nil, fmt.Errorf("error retrieving gitignore template list: %w", err)
}
selectTemmplates := &promptui.SelectTemplates{
selectTemplates := &promptui.SelectTemplates{
Label: ` {{ "\U0000007C" | faint }} {{ . | magenta | bold }}`,
Active: `{{ "\U0000007C" | faint }} {{ "🌶" | red }} {{ . | cyan | italic }}`,
Inactive: `{{ "\U0000007C" | faint }} {{ . | faint }}`,
@ -75,16 +85,17 @@ func runPrompt(client *github.Client, height int) (*github.Gitignore, error) {
}
prompt := promptui.Select{
Label: "Select a .gitignore template",
Items: templates,
Templates: selectTemmplates,
Size: height,
Searcher: filterFunc(templates),
Label: "Select a .gitignore template",
Items: templates,
Templates: selectTemplates,
Size: pc.Height,
Searcher: filterFunc(templates, pc.FilterType),
StartInSearchMode: pc.StartSearch,
}
i, _, err := prompt.Run()
if err != nil {
return nil, fmt.Errorf("error running selection prompt: %w", err)
return nil, err
}
content, _, err := client.Gitignores.Get(context.Background(), templates[i])
@ -97,7 +108,7 @@ func runPrompt(client *github.Client, height int) (*github.Gitignore, error) {
// commitGitignore writes the content of the selected gitignore template to the .gitignore file.
func commitGitignore(content *github.Gitignore, w io.Writer) error {
if _, err := fmt.Fprintf(w, "# Generated by ignr-cli: github.com/onyx-and-iris/ignr-cli\n\n## %s ##\n", content.GetName()); err != nil {
if _, err := fmt.Fprintf(w, "# Generated by ignr: github.com/onyx-and-iris/ignr\n\n## %s ##\n", content.GetName()); err != nil {
return fmt.Errorf("error writing header to file '%s': %w", gitignoreFileName, err)
}
@ -105,7 +116,7 @@ func commitGitignore(content *github.Gitignore, w io.Writer) error {
return fmt.Errorf("error writing to file '%s': %w", gitignoreFileName, err)
}
if _, err := fmt.Fprintf(w, "\n# End of ignr-cli\n"); err != nil {
if _, err := fmt.Fprintf(w, "\n# End of ignr\n"); err != nil {
return fmt.Errorf("error writing footer to file '%s': %w", gitignoreFileName, err)
}