commit 46b3081dec779154e1e7e384a5d2817c8cf10166
parent e38ad9499b99a03affe1dba77f911e84d8d0a7ca
Author: Sean Enck <sean@ttypty.com>
Date: Sat, 16 Jul 2022 09:41:02 -0400
restructure utils.go
Diffstat:
4 files changed, 212 insertions(+), 192 deletions(-)
diff --git a/internal/colors.go b/internal/colors.go
@@ -0,0 +1,40 @@
+package internal
+
+import (
+ "errors"
+)
+
+type (
+ // Color are terminal colors for dumb terminal coloring.
+ Color int
+)
+
+const (
+ termBeginRed = "\033[1;31m"
+ termEndRed = "\033[0m"
+ // ColorRed will get red terminal coloring.
+ ColorRed = iota
+)
+
+// GetColor will retrieve start/end terminal coloration indicators.
+func GetColor(color Color) (string, string, error) {
+ if color != ColorRed {
+ return "", "", errors.New("bad color")
+ }
+ interactive, err := IsInteractive()
+ if err != nil {
+ return "", "", err
+ }
+ colors := interactive
+ if colors {
+ isColored, err := isYesNoEnv(false, "LOCKBOX_NOCOLOR")
+ if err != nil {
+ return "", "", err
+ }
+ colors = !isColored
+ }
+ if colors {
+ return termBeginRed, termEndRed, nil
+ }
+ return "", "", nil
+}
diff --git a/internal/inputs.go b/internal/inputs.go
@@ -0,0 +1,121 @@
+package internal
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "os"
+ "strings"
+ "syscall"
+)
+
+func isYesNoEnv(defaultValue bool, env string) (bool, error) {
+ value := strings.ToLower(strings.TrimSpace(os.Getenv(env)))
+ if len(value) == 0 {
+ return defaultValue, nil
+ }
+ switch value {
+ case "no":
+ return false, nil
+ case "yes":
+ return true, nil
+ }
+ return false, fmt.Errorf("invalid yes/no env value for %s", env)
+}
+
+// IsInteractive indicates if running as a user UI experience.
+func IsInteractive() (bool, error) {
+ return isYesNoEnv(true, "LOCKBOX_INTERACTIVE")
+}
+
+func termEcho(on bool) {
+ // Common settings and variables for both stty calls.
+ attrs := syscall.ProcAttr{
+ Dir: "",
+ Env: []string{},
+ Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()},
+ Sys: nil}
+ var ws syscall.WaitStatus
+ cmd := "echo"
+ if !on {
+ cmd = "-echo"
+ }
+
+ // Enable/disable echoing.
+ pid, err := syscall.ForkExec(
+ "/bin/stty",
+ []string{"stty", cmd},
+ &attrs)
+ if err != nil {
+ panic(err)
+ }
+
+ // Wait for the stty process to complete.
+ _, err = syscall.Wait4(pid, &ws, 0, nil)
+ if err != nil {
+ panic(err)
+ }
+}
+
+// ConfirmInputsMatch will get 2 inputs and confirm they are the same.
+func ConfirmInputsMatch(object string) (string, error) {
+ termEcho(false)
+ defer func() {
+ termEcho(true)
+ }()
+ fmt.Printf("please enter %s: ", object)
+ first, err := Stdin(true)
+ if err != nil {
+ return "", err
+ }
+ fmt.Printf("\nplease re-enter %s: ", object)
+ second, err := Stdin(true)
+ if err != nil {
+ return "", err
+ }
+ if first != second {
+ return "", fmt.Errorf("%s(s) do NOT match", object)
+ }
+ return first, nil
+}
+
+// Stdin will retrieve stdin data.
+func Stdin(one bool) (string, error) {
+ b, err := getStdin(one)
+ if err != nil {
+ return "", err
+ }
+ return strings.TrimSpace(string(b)), nil
+}
+
+// IsInputFromPipe will indicate if connected to stdin pipe.
+func IsInputFromPipe() bool {
+ fileInfo, _ := os.Stdin.Stat()
+ return fileInfo.Mode()&os.ModeCharDevice == 0
+}
+
+// ConfirmYesNoPrompt will ask a yes/no question.
+func ConfirmYesNoPrompt(prompt string) (bool, error) {
+ fmt.Printf("%s? (y/N) ", prompt)
+ resp, err := Stdin(true)
+ if err != nil {
+ return false, err
+ }
+ return resp == "Y" || resp == "y", nil
+}
+
+func getStdin(one bool) ([]byte, error) {
+ scanner := bufio.NewScanner(os.Stdin)
+ var b bytes.Buffer
+ for scanner.Scan() {
+ b.WriteString(scanner.Text())
+ b.WriteString("\n")
+ if one {
+ break
+ }
+ }
+ if err := scanner.Err(); err != nil {
+ return nil, err
+ }
+ return b.Bytes(), nil
+}
diff --git a/internal/store.go b/internal/store.go
@@ -0,0 +1,51 @@
+package internal
+
+import (
+ "errors"
+ "io/fs"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+)
+
+const (
+ // Extension is the lockbox file extension.
+ Extension = ".lb"
+)
+
+// GetStore gets the lockbox directory.
+func GetStore() string {
+ return os.Getenv("LOCKBOX_STORE")
+}
+
+// List will get all lockbox files in a directory store.
+func List(store string, display bool) ([]string, error) {
+ var results []string
+ if !PathExists(store) {
+ return nil, errors.New("store does not exists")
+ }
+ err := filepath.Walk(store, func(path string, info fs.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+ if strings.HasSuffix(path, Extension) {
+ usePath := path
+ if display {
+ usePath = strings.TrimPrefix(usePath, store)
+ usePath = strings.TrimPrefix(usePath, "/")
+ usePath = strings.TrimSuffix(usePath, Extension)
+ }
+ results = append(results, usePath)
+ }
+ return nil
+ })
+
+ if err != nil {
+ return nil, err
+ }
+ if display {
+ sort.Strings(results)
+ }
+ return results, nil
+}
diff --git a/internal/utils.go b/internal/utils.go
@@ -1,176 +1,10 @@
package internal
import (
- "bufio"
- "bytes"
- "errors"
"fmt"
- "io/fs"
"os"
- "path/filepath"
- "sort"
- "strings"
- "syscall"
)
-type (
- // Color are terminal colors for dumb terminal coloring.
- Color int
-)
-
-const (
- // Extension is the lockbox file extension.
- Extension = ".lb"
- termBeginRed = "\033[1;31m"
- termEndRed = "\033[0m"
- // ColorRed will get red terminal coloring.
- ColorRed = iota
-)
-
-func isYesNoEnv(defaultValue bool, env string) (bool, error) {
- value := strings.ToLower(strings.TrimSpace(os.Getenv(env)))
- if len(value) == 0 {
- return defaultValue, nil
- }
- switch value {
- case "no":
- return false, nil
- case "yes":
- return true, nil
- }
- return false, fmt.Errorf("invalid yes/no env value for %s", env)
-}
-
-// IsInteractive indicates if running as a user UI experience.
-func IsInteractive() (bool, error) {
- return isYesNoEnv(true, "LOCKBOX_INTERACTIVE")
-}
-
-// GetColor will retrieve start/end terminal coloration indicators.
-func GetColor(color Color) (string, string, error) {
- if color != ColorRed {
- return "", "", errors.New("bad color")
- }
- interactive, err := IsInteractive()
- if err != nil {
- return "", "", err
- }
- colors := interactive
- if colors {
- isColored, err := isYesNoEnv(false, "LOCKBOX_NOCOLOR")
- if err != nil {
- return "", "", err
- }
- colors = !isColored
- }
- if colors {
- return termBeginRed, termEndRed, nil
- }
- return "", "", nil
-}
-
-// GetStore gets the lockbox directory.
-func GetStore() string {
- return os.Getenv("LOCKBOX_STORE")
-}
-
-// List will get all lockbox files in a directory store.
-func List(store string, display bool) ([]string, error) {
- var results []string
- if !PathExists(store) {
- return nil, errors.New("store does not exists")
- }
- err := filepath.Walk(store, func(path string, info fs.FileInfo, err error) error {
- if err != nil {
- return err
- }
- if strings.HasSuffix(path, Extension) {
- usePath := path
- if display {
- usePath = strings.TrimPrefix(usePath, store)
- usePath = strings.TrimPrefix(usePath, "/")
- usePath = strings.TrimSuffix(usePath, Extension)
- }
- results = append(results, usePath)
- }
- return nil
- })
-
- if err != nil {
- return nil, err
- }
- if display {
- sort.Strings(results)
- }
- return results, nil
-}
-
-func termEcho(on bool) {
- // Common settings and variables for both stty calls.
- attrs := syscall.ProcAttr{
- Dir: "",
- Env: []string{},
- Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()},
- Sys: nil}
- var ws syscall.WaitStatus
- cmd := "echo"
- if !on {
- cmd = "-echo"
- }
-
- // Enable/disable echoing.
- pid, err := syscall.ForkExec(
- "/bin/stty",
- []string{"stty", cmd},
- &attrs)
- if err != nil {
- panic(err)
- }
-
- // Wait for the stty process to complete.
- _, err = syscall.Wait4(pid, &ws, 0, nil)
- if err != nil {
- panic(err)
- }
-}
-
-// ConfirmInputsMatch will get 2 inputs and confirm they are the same.
-func ConfirmInputsMatch(object string) (string, error) {
- termEcho(false)
- defer func() {
- termEcho(true)
- }()
- fmt.Printf("please enter %s: ", object)
- first, err := Stdin(true)
- if err != nil {
- return "", err
- }
- fmt.Printf("\nplease re-enter %s: ", object)
- second, err := Stdin(true)
- if err != nil {
- return "", err
- }
- if first != second {
- return "", fmt.Errorf("%s(s) do NOT match", object)
- }
- return first, nil
-}
-
-// Stdin will retrieve stdin data.
-func Stdin(one bool) (string, error) {
- b, err := getStdin(one)
- if err != nil {
- return "", err
- }
- return strings.TrimSpace(string(b)), nil
-}
-
-// IsInputFromPipe will indicate if connected to stdin pipe.
-func IsInputFromPipe() bool {
- fileInfo, _ := os.Stdin.Stat()
- return fileInfo.Mode()&os.ModeCharDevice == 0
-}
-
// LogError will log an error to stderr.
func LogError(message string, err error) {
msg := message
@@ -195,29 +29,3 @@ func PathExists(path string) bool {
}
return true
}
-
-// ConfirmYesNoPrompt will ask a yes/no question.
-func ConfirmYesNoPrompt(prompt string) (bool, error) {
- fmt.Printf("%s? (y/N) ", prompt)
- resp, err := Stdin(true)
- if err != nil {
- return false, err
- }
- return resp == "Y" || resp == "y", nil
-}
-
-func getStdin(one bool) ([]byte, error) {
- scanner := bufio.NewScanner(os.Stdin)
- var b bytes.Buffer
- for scanner.Scan() {
- b.WriteString(scanner.Text())
- b.WriteString("\n")
- if one {
- break
- }
- }
- if err := scanner.Err(); err != nil {
- return nil, err
- }
- return b.Bytes(), nil
-}