Merge pull request #531 from chrisallenlane/auto-config

feat(configs): config auto-generation
This commit is contained in:
Chris Allen Lane 2020-01-29 14:22:12 -05:00 committed by GitHub
commit d4c6200702
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 125 additions and 66 deletions

View File

@ -33,7 +33,7 @@ releases := \
## build: builds an executable for your architecture ## build: builds an executable for your architecture
.PHONY: build .PHONY: build
build: $(dist_dir) build: $(dist_dir) clean generate
$(GO) build $(BUILD_FLAGS) -o $(dist_dir)/cheat $(cmd_dir) $(GO) build $(BUILD_FLAGS) -o $(dist_dir)/cheat $(cmd_dir)
## build-release: builds release executables ## build-release: builds release executables
@ -47,27 +47,27 @@ ci: | setup prepare build
# cheat-darwin-amd64 # cheat-darwin-amd64
$(dist_dir)/cheat-darwin-amd64: prepare $(dist_dir)/cheat-darwin-amd64: prepare
GOARCH=amd64 GOOS=darwin \ GOARCH=amd64 GOOS=darwin \
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ $(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ && chmod -x $@.gz
# cheat-linux-amd64 # cheat-linux-amd64
$(dist_dir)/cheat-linux-amd64: prepare $(dist_dir)/cheat-linux-amd64: prepare
GOARCH=amd64 GOOS=linux \ GOARCH=amd64 GOOS=linux \
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ $(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ && chmod -x $@.gz
# cheat-linux-arm5 # cheat-linux-arm5
$(dist_dir)/cheat-linux-arm5: prepare $(dist_dir)/cheat-linux-arm5: prepare
GOARCH=arm GOOS=linux GOARM=5 \ GOARCH=arm GOOS=linux GOARM=5 \
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ $(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ && chmod -x $@.gz
# cheat-linux-arm6 # cheat-linux-arm6
$(dist_dir)/cheat-linux-arm6: prepare $(dist_dir)/cheat-linux-arm6: prepare
GOARCH=arm GOOS=linux GOARM=6 \ GOARCH=arm GOOS=linux GOARM=6 \
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ $(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ && chmod -x $@.gz
# cheat-linux-arm7 # cheat-linux-arm7
$(dist_dir)/cheat-linux-arm7: prepare $(dist_dir)/cheat-linux-arm7: prepare
GOARCH=arm GOOS=linux GOARM=7 \ GOARCH=arm GOOS=linux GOARM=7 \
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ $(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ && chmod -x $@.gz
# cheat-windows-amd64 # cheat-windows-amd64
$(dist_dir)/cheat-windows-amd64.exe: prepare $(dist_dir)/cheat-windows-amd64.exe: prepare
@ -95,7 +95,7 @@ clean: $(dist_dir)
## distclean: removes the tags file ## distclean: removes the tags file
.PHONY: distclean .PHONY: distclean
distclean: distclean:
$(RM) tags $(RM) -f tags
## setup: installs revive (linter) and scc (sloc tool) ## setup: installs revive (linter) and scc (sloc tool)
.PHONY: setup .PHONY: setup
@ -110,7 +110,7 @@ sloc:
## tags: builds a tags file ## tags: builds a tags file
.PHONY: tags .PHONY: tags
tags: tags:
$(CTAGS) -R . --exclude=vendor $(CTAGS) -R --exclude=vendor --languages=go
## vendor: downloads, tidies, and verifies dependencies ## vendor: downloads, tidies, and verifies dependencies
.PHONY: vendor .PHONY: vendor

View File

@ -13,7 +13,7 @@ import (
"github.com/cheat/cheat/internal/config" "github.com/cheat/cheat/internal/config"
) )
const version = "3.3.2" const version = "3.4.0"
func main() { func main() {
@ -31,13 +31,35 @@ func main() {
os.Exit(0) os.Exit(0)
} }
// load the config file // load the os-specifc paths at which the config file may be located
confpath, err := config.Path(runtime.GOOS) confpaths, err := config.Paths(runtime.GOOS)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "could not locate config file") fmt.Fprintf(os.Stderr, "failed to load config: %v\n", err)
os.Exit(1) os.Exit(1)
} }
// search for the config file in the above paths
confpath, err := config.Path(confpaths)
if err != nil {
// the config file does not exist, so we'll try to create one
if err = config.Init(confpaths[0], configs()); err != nil {
fmt.Fprintf(
os.Stderr,
"failed to create config file: %s: %v\n",
confpaths[0],
err,
)
os.Exit(1)
}
confpath = confpaths[0]
fmt.Printf("Created config file: %s\n", confpath)
fmt.Println("Please edit this file now to configure cheat.")
os.Exit(0)
}
// initialize the configs // initialize the configs
conf, err := config.New(opts, confpath, true) conf, err := config.New(opts, confpath, true)
if err != nil { if err != nil {

View File

@ -43,22 +43,23 @@ cheatpaths:
# #
# Note that the paths and tags listed below are just examples. You may freely # Note that the paths and tags listed below are just examples. You may freely
# change them to suit your needs. # change them to suit your needs.
#
# TODO: regarding community cheatsheets: these must be installed separately.
# You may download them here:
#
# https://github.com/cheat/cheatsheets
#
# Once downloaded, ensure that 'path' below points to the location at which
# you downloaded the community cheatsheets.
- name: community - name: community
path: ~/.dotfiles/cheat/community path: ~/cheat/cheatsheets/community
tags: [ community ] tags: [ community ]
readonly: true readonly: true
# Maybe your company or department maintains a repository of cheatsheets as
# well. It's probably sensible to list those second.
- name: work
path: ~/.dotfiles/cheat/work
tags: [ work ]
readonly: false
# If you have personalized cheatsheets, list them last. They will take # If you have personalized cheatsheets, list them last. They will take
# precedence over the more global cheatsheets. # precedence over the more global cheatsheets.
- name: personal - name: personal
path: ~/.dotfiles/cheat/personal path: ~/cheat/cheatsheets/personal
tags: [ personal ] tags: [ personal ]
readonly: false readonly: false

View File

@ -34,22 +34,23 @@ cheatpaths:
# #
# Note that the paths and tags listed below are just examples. You may freely # Note that the paths and tags listed below are just examples. You may freely
# change them to suit your needs. # change them to suit your needs.
#
# TODO: regarding community cheatsheets: these must be installed separately.
# You may download them here:
#
# https://github.com/cheat/cheatsheets
#
# Once downloaded, ensure that 'path' below points to the location at which
# you downloaded the community cheatsheets.
- name: community - name: community
path: ~/.dotfiles/cheat/community path: ~/cheat/cheatsheets/community
tags: [ community ] tags: [ community ]
readonly: true readonly: true
# Maybe your company or department maintains a repository of cheatsheets as
# well. It's probably sensible to list those second.
- name: work
path: ~/.dotfiles/cheat/work
tags: [ work ]
readonly: false
# If you have personalized cheatsheets, list them last. They will take # If you have personalized cheatsheets, list them last. They will take
# precedence over the more global cheatsheets. # precedence over the more global cheatsheets.
- name: personal - name: personal
path: ~/.dotfiles/cheat/personal path: ~/cheat/cheatsheets/personal
tags: [ personal ] tags: [ personal ]
readonly: false readonly: false

View File

@ -75,14 +75,16 @@ func New(opts map[string]interface{}, confPath string, resolve bool) (Config, er
// `resolve` is a switch that allows us to turn off symlink resolution when // `resolve` is a switch that allows us to turn off symlink resolution when
// running the config tests. // running the config tests.
if resolve { if resolve {
expanded, err = filepath.EvalSymlinks(expanded) evaled, err := filepath.EvalSymlinks(expanded)
if err != nil { if err != nil {
return Config{}, fmt.Errorf( return Config{}, fmt.Errorf(
"failed to resolve symlink: %s, %v", "failed to resolve symlink: %s: %v",
expanded, expanded,
err, err,
) )
} }
expanded = evaled
} }
conf.Cheatpaths[i].Path = expanded conf.Cheatpaths[i].Path = expanded

24
internal/config/init.go Normal file
View File

@ -0,0 +1,24 @@
package config
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
)
// Init initializes a config file
func Init(confpath string, configs string) error {
// assert that the config directory exists
if err := os.MkdirAll(filepath.Dir(confpath), 0755); err != nil {
return fmt.Errorf("failed to create directory: %v", err)
}
// write the config file
if err := ioutil.WriteFile(confpath, []byte(configs), 0644); err != nil {
return fmt.Errorf("failed to create file: %v", err)
}
return nil
}

View File

@ -3,43 +3,10 @@ package config
import ( import (
"fmt" "fmt"
"os" "os"
"path"
"github.com/mitchellh/go-homedir"
) )
// Path returns the config file path // Path returns the config file path
func Path(sys string) (string, error) { func Path(paths []string) (string, error) {
var paths []string
// if CHEAT_CONFIG_PATH is set, return it
if os.Getenv("CHEAT_CONFIG_PATH") != "" {
// expand ~
expanded, err := homedir.Expand(os.Getenv("CHEAT_CONFIG_PATH"))
if err != nil {
return "", fmt.Errorf("failed to expand ~: %v", err)
}
return expanded, nil
}
switch sys {
case "darwin", "linux", "freebsd":
paths = []string{
path.Join(os.Getenv("XDG_CONFIG_HOME"), "/cheat/conf.yml"),
path.Join(os.Getenv("HOME"), ".config/cheat/conf.yml"),
path.Join(os.Getenv("HOME"), ".cheat/conf.yml"),
}
case "windows":
paths = []string{
fmt.Sprintf("%s/cheat/conf.yml", os.Getenv("APPDATA")),
fmt.Sprintf("%s/cheat/conf.yml", os.Getenv("PROGRAMDATA")),
}
default:
return "", fmt.Errorf("unsupported os: %s", sys)
}
// check if the config file exists on any paths // check if the config file exists on any paths
for _, p := range paths { for _, p := range paths {

42
internal/config/paths.go Normal file
View File

@ -0,0 +1,42 @@
package config
import (
"fmt"
"os"
"path"
"github.com/mitchellh/go-homedir"
)
// Paths returns config file paths that are appropriate for the operating
// system
func Paths(sys string) ([]string, error) {
// if CHEAT_CONFIG_PATH is set, return it
if os.Getenv("CHEAT_CONFIG_PATH") != "" {
// expand ~
expanded, err := homedir.Expand(os.Getenv("CHEAT_CONFIG_PATH"))
if err != nil {
return []string{}, fmt.Errorf("failed to expand ~: %v", err)
}
return []string{expanded}, nil
}
switch sys {
case "darwin", "linux", "freebsd":
return []string{
path.Join(os.Getenv("XDG_CONFIG_HOME"), "/cheat/conf.yml"),
path.Join(os.Getenv("HOME"), ".config/cheat/conf.yml"),
path.Join(os.Getenv("HOME"), ".cheat/conf.yml"),
}, nil
case "windows":
return []string{
fmt.Sprintf("%s/cheat/conf.yml", os.Getenv("APPDATA")),
fmt.Sprintf("%s/cheat/conf.yml", os.Getenv("PROGRAMDATA")),
}, nil
default:
return []string{}, fmt.Errorf("unsupported os: %s", sys)
}
}