129 lines
2.6 KiB
Go
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
|
|
}
|