bbash/command/tail/tail.go
2025-01-14 17:06:25 +01:00

129 lines
2.6 KiB
Go

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
}