package tail import ( "bbash/environment" "bbash/input_parser" "bufio" "bytes" "fmt" "io" "os" "slices" "strconv" "strings" ) func Tail(in input_parser.Input, env *environment.Env) { flagsArray := []string{ "n", "help", } flagsDictionary := map[string]string{ "n": "-n displays the line numbers", "help": "-help shows this message", } if slices.Contains(in.Flags, "help") { fmt.Printf("Lists Sources in the current working directory\n") fmt.Printf("Supported flags are:\n") for _, flag := range flagsArray { fmt.Println(flag + flagsDictionary[flag]) } // Print flags and there description return } args := in.Args var file_path string var lines int if len(args) >= 1 { file_path = strings.TrimSpace(args[0]) } else { fmt.Print(fmt.Sprintf("No arguments provided")) return } if len(args) == 2 { lines1, err := strconv.Atoi(strings.TrimSpace(args[1])) lines = lines1 if err != nil { fmt.Print(fmt.Sprintf("Second argument must be a integer")) return } } file, err := os.Open(file_path) if err != nil { fmt.Println(fmt.Sprintf("Error opening file: %s", err.Error())) return } defer file.Close() size, err := CountLines(file) file.Seek(0, io.SeekStart) scanner := bufio.NewScanner(file) if lines == 0 { if slices.Contains(in.Flags, "n") { for i := 0; i < size; i++ { if !scanner.Scan() { return } if i >= (size - 10) { fmt.Println(fmt.Sprintf(strconv.FormatInt(int64(i), 10) + scanner.Text())) } } } else { for i := 0; i < size; i++ { if !scanner.Scan() { return } if i >= (size - 10) { fmt.Println(fmt.Sprintf(scanner.Text())) } } } } else { if slices.Contains(in.Flags, "n") { var counter int for counter := 0; counter < size-1; counter++ { if !scanner.Scan() { return } if counter >= (size - lines) { fmt.Println(fmt.Sprintf(strconv.FormatInt(int64(counter), 10) + scanner.Text())) } } scanner.Scan() fmt.Print(fmt.Sprintf(strconv.FormatInt(int64(counter), 10) + scanner.Text())) } else { for i := 0; i < size-1; i++ { if !scanner.Scan() { return } if i >= (size - lines) { fmt.Println(fmt.Sprintf(scanner.Text())) } } scanner.Scan() fmt.Print(fmt.Sprintf(scanner.Text())) } } } func CountLines(r io.Reader) (int, error) { var count int var read int var err error var target []byte = []byte("\n") buffer := make([]byte, 32*1024) for { read, err = r.Read(buffer) if err != nil { break } count += bytes.Count(buffer[:read], target) } if err == io.EOF { return count, nil } return count, err }