package main import ( "bufio" "errors" "flag" "fmt" "jsh" "os" "regexp" "strconv" ) func ConvertUnit(stringUnit string) (jsh.Unit, error) { switch stringUnit { case "B": return jsh.B, nil case "kB": return jsh.KB, nil case "mB": return jsh.MB, nil case "gB": return jsh.GB, nil case "tB": return jsh.TB, nil case "": // On some systems (Arch, for example) bytes are just the empty string return jsh.B, nil default: return 0, errors.New(fmt.Sprintf("Unknown unit: %s\n", stringUnit)) } } func ParseLine(line string) (string, jsh.MemStat, error) { // Recognizes a alphanumeric or () word, the : character, whitespace, the number we're looking for, // more whitespace, and possibly the unit lineRegex := regexp.MustCompile("(?P^[\\w()]+):\\s+(?P\\d+)(\\s+)?(?P\\w+)?") // Parse the line, and construct a map of the valid matches parsedLine := lineRegex.FindStringSubmatch(line) names := lineRegex.SubexpNames() matchedVals := map[string]string{} for i, n := range parsedLine { matchedVals[names[i]] = n } key := matchedVals["key"] val, err := strconv.Atoi(matchedVals["val"]) if err != nil { return "", jsh.MemStat{}, err } unit, err := ConvertUnit(matchedVals["unit"]) if err != nil { return "", jsh.MemStat{}, err } return key, jsh.MemStat{val, unit}, nil } func parseMemInfo() jsh.JshFrame { file, err := os.Open("/proc/meminfo") if err != nil { return jsh.JshFrame{[]string{}, []error{err}} } defer file.Close() scanner := bufio.NewScanner(file) memInfo := make(map[string]jsh.MemStat) errors := []error{} // Read in each line of the meminfo file, and place it in the map for scanner.Scan() { key, val, err := ParseLine(scanner.Text()) if err != nil { errors = append(errors, err) } memInfo[key] = val } // Wrap with array stdOut := []map[string]jsh.MemStat{memInfo} finalOut := jsh.JshFrame{stdOut, errors} return finalOut } func runJsonMode() { output := parseMemInfo() queue := make(chan *jsh.JshFrame) done := make(chan bool) go jsh.OutputFrames(queue, done) queue <- &output close(queue) <-done } func main() { jsonModePtr := flag.Bool("json", false, "whether to use json mode for output") flag.Parse() if !*jsonModePtr { fmt.Printf("%s", jsh.Fallback("free")) } else { runJsonMode() } }