package main import ( "fmt" "log" "strconv" "strings" "github.com/beanzilla/gonode" "golang.org/x/exp/slices" ) // Strips out the tabs in the line and returns the text func Text(n *gonode.Node) string { if n.Data() == nil { return "" } txt := fmt.Sprintf("%v", n.Data()) for strings.HasPrefix(txt, "\t") { txt = txt[1:] } return txt } // Endless sky stores most data as 'key value' // // With special cases: // // As String '"some key" value' (Or '"some key" "some value"') // // As Int: '"some key" 13' // // As Float: '"some key" 9.81' // // Return's key part func Key(text string) string { parts := strings.Split(text, " ") if strings.Contains(parts[0], "\"") { pref := "" for _, part := range parts { if strings.HasSuffix(part, "\"") { if pref != "" { pref += " " } pref += part break } if pref != "" { pref += " " } pref += part } pref = strings.ReplaceAll(pref, "\"", "") return pref } return parts[0] } // Endless sky stores mose data as 'key value' // // With special cases: // // As String '"some key" value' (Or '"some key" "some value"') // // As Int: '"some key" 13' // // As Float: '"some key" 9.81' // // Return's value part (as string) func Value(text string) string { key := Key(text) val := strings.Replace(text, Format(key)+" ", "", 1) val = strings.ReplaceAll(val, "\"", "") return val } // Returns the value as integer (errors return 0) func ValueInt(text string) int { v, err := strconv.Atoi(Value(text)) if err != nil { log.Printf("ValueInt('%s') => %v", Value(text), err) return 0 } return v } // Returns the value as float64 (errors return 0.0) func ValueFloat64(text string) float64 { v, err := strconv.ParseFloat(text, 64) if err != nil { log.Printf("ValueFloat64('%s') => %v", Value(text), err) return 0.0 } return v } // Format function // // Endless sky demands any multi word key or value must be wrapped in "s // // Both Node.Key() and Node.Value() remove the "s so this must be called to form the new Node.Line (for setters) func Format(text string) string { if strings.Contains(text, " ") { return "\"" + text + "\"" } return text } // Checks if the given text could be converted to an integer // // Might want to check IsFloat first (as it includes '.') func IsInt(text string) bool { negative := false numbers := []rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'} for _, char := range text { if char == '-' { if !negative { negative = true } else { return false } continue } if !slices.Contains(numbers, char) { return false } } return true } // Checks if the given text could be converted to a float // // Might want to check IsInt after (this checks '.') func IsFloat(text string) bool { negative := false point := false numbers := []rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'} for _, char := range text { if char == '-' { if !negative { negative = true } else { return false } continue } if char == '.' { if !point { point = true } else { return false } continue } if !slices.Contains(numbers, char) { return false } } /* This won't require a '.' somewhere in it if !point { return false }*/ return true }