7 Commits

5 changed files with 39 additions and 31 deletions

View File

@@ -43,9 +43,9 @@ var possibleColors map[string]color = map[string]color{
"WHITE": {"WHITE", colorData.New(colorData.FgWhite)}, "WHITE": {"WHITE", colorData.New(colorData.FgWhite)},
"GRAY": {"GRAY", colorData.New(colorData.FgWhite, colorData.Faint)}, "GRAY": {"GRAY", colorData.New(colorData.FgWhite, colorData.Faint)},
// Last three numbers are RGB. Reference https://en.wikipedia.org/wiki/ANSI_escape_code for what the first two numbers mean. // Last three numbers are RGB. Reference https://en.wikipedia.org/wiki/ANSI_escape_code for what the first two numbers mean.
// "ORANGE": {"ORANGE", colorData.New(38, 2, 255, 153, 28)}, // "ORANGE": {"ORANGE", colorData.New(38, 2, 255, 153, 28)},
// "DARKBLUE": {"DARKBLUE", colorData.New(38, 2, 0, 112, 255)}, // "DARKBLUE": {"DARKBLUE", colorData.New(38, 2, 0, 112, 255)},
"NONE": {"NONE", colorData.New()}, "NONE": {"NONE", colorData.New()},
} }
// Apply the given color 'clr' to all units in 'units', within the indices // Apply the given color 'clr' to all units in 'units', within the indices
@@ -95,9 +95,7 @@ func stringToRGB(rgbString string) (*RGB, error) {
values := strings.Split(rgbString, " ") values := strings.Split(rgbString, " ")
// There must be three space-separated strings. // There must be three space-separated strings.
if len(values) != 5 { if len(values) != 5 {
// TODO: Instead of ignoring these errors and returning a generic error (as I do in the return nil, fmt.Errorf("Must be exactly five space-separated numbers per line")
// callee), wrap the error returned from this function, inside the error returned by the callee.
return nil, fmt.Errorf("Error parsing RGB five-tuple.")
} }
// If any of the strings doesn't represent an integer (or is out of bounds), return an error. // If any of the strings doesn't represent an integer (or is out of bounds), return an error.
// WARNING: LAZY CODE INCOMING // WARNING: LAZY CODE INCOMING
@@ -105,43 +103,46 @@ func stringToRGB(rgbString string) (*RGB, error) {
var err error var err error
toReturn.sgr1, err = strconv.Atoi(values[0]) toReturn.sgr1, err = strconv.Atoi(values[0])
if err != nil { if err != nil {
return nil, fmt.Errorf("Error parsing SGR1 integer: Invalid value.") return nil, fmt.Errorf("Invalid value for first number (try 38 for default)")
} }
if toReturn.sgr1 < 0 || toReturn.sgr1 > 107 { // Maximum value for SGR values if toReturn.sgr1 < 0 || toReturn.sgr1 > 107 { // Maximum value for SGR values
return nil, fmt.Errorf("Error parsing SGR1 integer: Out-of-bounds.") return nil, fmt.Errorf("First number out-of-bounds 0 to 107 (try 38 for default)")
} }
toReturn.red, err = strconv.Atoi(values[1]) toReturn.red, err = strconv.Atoi(values[1])
if err != nil { if err != nil {
return nil, fmt.Errorf("Error parsing RED integer: Invalid value.") return nil, fmt.Errorf("Invalid value for RED Integer (number 2)")
} }
if toReturn.red < -1 || toReturn.red > 255 { if toReturn.red < -1 || toReturn.red > 255 {
return nil, fmt.Errorf("Error parsing RED integer: Out-of-bounds.") return nil, fmt.Errorf("RED Integer (number 2) out-of-bounds")
} }
toReturn.blue, err = strconv.Atoi(values[2])
toReturn.green, err = strconv.Atoi(values[2])
if err != nil { if err != nil {
return nil, fmt.Errorf("Error parsing BLUE integer: Invalid value.") return nil, fmt.Errorf("Invalid value for GREEN Integer (number 3)")
}
if toReturn.blue < -1 || toReturn.blue > 255 {
return nil, fmt.Errorf("Error parsing BLUE integer: Out-of-bounds.")
}
toReturn.green, err = strconv.Atoi(values[3])
if err != nil {
return nil, fmt.Errorf("Error parsing GREEN integer: Invalid value.")
} }
if toReturn.green < -1 || toReturn.green > 255 { if toReturn.green < -1 || toReturn.green > 255 {
return nil, fmt.Errorf("Error parsing GREEN integer: Out-of-bounds.") return nil, fmt.Errorf("GREEN Integer (number 3) out-of-bounds")
} }
toReturn.blue, err = strconv.Atoi(values[3])
if err != nil {
return nil, fmt.Errorf("Invalid value for BLUE Integer (number 4)")
}
if toReturn.blue < -1 || toReturn.blue > 255 {
return nil, fmt.Errorf("BLUE Integer (number 4) out-of-bounds")
}
toReturn.sgr2, err = strconv.Atoi(values[4]) toReturn.sgr2, err = strconv.Atoi(values[4])
if err != nil { if err != nil {
return nil, fmt.Errorf("Error parsing SGR2 integer: Invalid value.") return nil, fmt.Errorf("Invalid value for last number (try 22 for default)")
} }
if toReturn.sgr2 < 0 || toReturn.sgr2 > 107 { if toReturn.sgr2 < 0 || toReturn.sgr2 > 107 { // Maximum value for SGR values
return nil, fmt.Errorf("Error parsing SGR2 integer: Out-of-bounds.") return nil, fmt.Errorf("Last number out-of-bounds 0 to 107 (try 22 for default)")
} }
if !(toReturn.red > 0 && toReturn.blue > 0 && toReturn.green > 0) && if !(toReturn.red > 0 && toReturn.blue > 0 && toReturn.green > 0) &&
!(toReturn.red == -1 && toReturn.green == -1 && toReturn.blue == -1) { !(toReturn.red == -1 && toReturn.green == -1 && toReturn.blue == -1) {
return nil, fmt.Errorf("Error parsing color: All values must be positive or -1 for default terminal color.") return nil, fmt.Errorf("RGB values must be positive or -1 for default terminal color")
} }
return &toReturn, nil return &toReturn, nil
} }
@@ -157,7 +158,7 @@ func stringToRGB(rgbString string) (*RGB, error) {
func loadColorsFromFile(filepath string) error { func loadColorsFromFile(filepath string) error {
data, err := os.ReadFile(filepath) data, err := os.ReadFile(filepath)
if err != nil { if err != nil {
panic(err) return err
} }
// Read color config file into a MapSlice // Read color config file into a MapSlice
tempMapSlice := yaml.MapSlice{} tempMapSlice := yaml.MapSlice{}
@@ -171,7 +172,7 @@ func loadColorsFromFile(filepath string) error {
} }
var rgb *RGB var rgb *RGB
if rgb, err = stringToRGB(item.Value.(string)); err != nil { if rgb, err = stringToRGB(item.Value.(string)); err != nil {
return fmt.Errorf("Invalid RGB trio: %s", item.Value.(string)) return fmt.Errorf("Error parsing color line %s:\t%v", item.Value.(string), err)
} }
// If we haven't returned an error yet, the color must be valid. // If we haven't returned an error yet, the color must be valid.
// Add it to the map. colorData.New() expects values of type colorData.Attribute, // Add it to the map. colorData.New() expects values of type colorData.Attribute,

View File

@@ -3,6 +3,7 @@ package main
import ( import (
"embed" "embed"
"errors" "errors"
"fmt"
"io/fs" "io/fs"
"os" "os"
"path/filepath" "path/filepath"
@@ -15,7 +16,7 @@ import (
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
//go:embed config //go:embed config/*
var storedConfigs embed.FS // Embed the folder containing config files var storedConfigs embed.FS // Embed the folder containing config files
// runningOnWindows: At the moment this function isn't used. When Window support is added, // runningOnWindows: At the moment this function isn't used. When Window support is added,
@@ -88,7 +89,10 @@ func loadConfig(configFilename string) (stack.Stack[regColor], error) {
// returned. // returned.
regColorStack := stack.NewStack[regColor](len(strings.Split(string(configFile), "\n"))) // The stack will have the same size as the number of lines in the file regColorStack := stack.NewStack[regColor](len(strings.Split(string(configFile), "\n"))) // The stack will have the same size as the number of lines in the file
for _, item := range tempMapSlice { for _, item := range tempMapSlice {
re := regex.MustCompile(item.Key.(string), regex.RE_MULTILINE, regex.RE_SINGLE_LINE) re, err := regex.Compile(item.Key.(string), regex.RE_MULTILINE, regex.RE_SINGLE_LINE)
if err != nil {
return *stack.NewStack[regColor](0), fmt.Errorf("%v: '%s'", err, item.Key.(string))
}
clr, err := newColor(item.Value.(string)) clr, err := newColor(item.Value.(string))
if err != nil { if err != nil {
return *stack.NewStack[regColor](0), err return *stack.NewStack[regColor](0), err

View File

@@ -1,8 +1,9 @@
# The first and last fields are SGR values, used to control things # The first and last fields are SGR values, used to control things
# like bold and italic text. If you're unsure what to put, use '38' # like bold and italic text. If you're unsure what to put, use '38'
# for the first one and '22' for the last one, for normal text. # for the first one and '22' for the last one, for normal text.
# The last three values are R G B values. # The middle three values are R G B values.
PINK: 38 244 211 244 22 PINK: 38 244 211 244 22
BOLD_WHITE: 38 -1 -1 -1 1 BOLD_WHITE: 38 -1 -1 -1 1
ITALIC_WHITE: 38 -1 -1 -1 3 ITALIC_WHITE: 38 -1 -1 -1 3
UNDERLINE_WHITE: 38 -1 -1 -1 4 UNDERLINE_WHITE: 38 -1 -1 -1 4
DARKBLUE: 38 1 1 139 22

View File

@@ -14,6 +14,8 @@
# Bold text # Bold text
'\b__[^_]+?__\b': BOLD_WHITE '\b__[^_]+?__\b': BOLD_WHITE
'\*\*[^*]+?\*\*': BOLD_WHITE
# Italic text # Italic text
'\b_[^_]+?_\b': ITALIC_WHITE '\b_[^_]+?_\b': ITALIC_WHITE
'\*[^*\n]+?\*': ITALIC_WHITE

View File

@@ -79,7 +79,7 @@ func main() {
// Check if config exists. If it doesn't, generate the config files. // Check if config exists. If it doesn't, generate the config files.
userHomeDir, err := os.UserHomeDir() // Get current user's home directory, to construct config path userHomeDir, err := os.UserHomeDir() // Get current user's home directory, to construct config path
if err != nil { if err != nil {
panic(err) printErrAndExit("Unable to retrieve user home directory")
} }
configPath := filepath.Join(userHomeDir + "/.config/ccat/") configPath := filepath.Join(userHomeDir + "/.config/ccat/")
if _, err := os.Stat(configPath); os.IsNotExist(err) { if _, err := os.Stat(configPath); os.IsNotExist(err) {
@@ -107,7 +107,7 @@ func main() {
// the program. // the program.
finfo, err := os.Stat(fileName) finfo, err := os.Stat(fileName)
if err != nil { if err != nil {
panic(err) printErrAndExit("Unable to read file")
} }
if finfo.Size() == 0 { if finfo.Size() == 0 {
os.Exit(0) os.Exit(0)