Let's make a simple counter to check how many lines of code are in our project.
I want to start with a simple function.
func LineCounter(r string) (int, error) {
var count int
rr := strings.Split(r, "\n")
var rrr []string
cc := 0
comstart := false
for _, str := range rr {
if strings.HasPrefix(str, "/*") {
comstart = true
continue
}
if strings.Contains(str, "*/") {
comstart = false
cc += 1
}
if (str != "" && !strings.HasPrefix(str, "//") && !comstart) {
rrr = append(rrr, str)
}
}
count = len(rrr) - cc
return count, nil
}
This function takes some text and split all lines by "\n" (newline sign). We check if 2 things if the line is empty and also if the line is any kind of comment. In golang there is a single-line comment starting with // and also multiline starting with / and end with /. The function return number of lines or error.
var (
Info = Teal
Warn = Yellow
Fata = Red
)
var (
Black = Color("\033[1;30m%s\033[0m")
Red = Color("\033[1;31m%s\033[0m")
Green = Color("\033[1;32m%s\033[0m")
Yellow = Color("\033[1;33m%s\033[0m")
Purple = Color("\033[1;34m%s\033[0m")
Magenta = Color("\033[1;35m%s\033[0m")
Teal = Color("\033[1;36m%s\033[0m")
White = Color("\033[1;37m%s\033[0m")
)
func Color(colorString string) func(...interface{}) string {
sprint := func(args ...interface{}) string {
return fmt.Sprintf(colorString,
fmt.Sprint(args...))
}
return sprint
}
This part of the code we use to create colored text doesn't need explanation I guess.
Last but not least we have the main function.
func main() {
arg := os.Args[1]
all := 0
err := filepath.Walk(arg, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if (!info.IsDir() && !strings.Contains(info.Name(), "test") ){
ext := filepath.Ext(path)
if ext == ".go" {
jj, _ := os.ReadFile(path)
g, _ := LineCounter(string(jj))
all += g
var u string
if g < 200 {
z := strconv.Itoa(g)
u = Info(z)
}
if g >= 200 && g < 1000 {
z := strconv.Itoa(g)
u = Warn(z)
}
if g >= 1000 {
z := strconv.Itoa(g)
u = Fata(z)
}
fmt.Printf("File %s have %s lines of code \n",path, u)
}
}
return nil
})
if err != nil {
log.Println(err)
}
fmt.Println("All lines", all)
}
Here I get my path from the console and go through it recursively checking if the path is not a folder. If the path is not a folder (it is a file) and if the file has ".go" extension. I also check if the filename contains "test" word. I don't want to count test files (In golang test files must contain test after the name). I add to sum every time when our LineCounter function returns a number. I check if a number of lines are less than 200 converts the number to a string and make it teal, 200-1000 Yellow, and everything more than 1000 is red. I also print every file with a number of lines. And on end, I print the sum of all lines.
Finally our completed code.
package main
import (
"fmt"
"log"
"os"
"path/filepath"
"strconv"
"strings"
)
var (
Info = Teal
Warn = Yellow
Fata = Red
)
var (
Black = Color("\033[1;30m%s\033[0m")
Red = Color("\033[1;31m%s\033[0m")
Green = Color("\033[1;32m%s\033[0m")
Yellow = Color("\033[1;33m%s\033[0m")
Purple = Color("\033[1;34m%s\033[0m")
Magenta = Color("\033[1;35m%s\033[0m")
Teal = Color("\033[1;36m%s\033[0m")
White = Color("\033[1;37m%s\033[0m")
)
func Color(colorString string) func(...interface{}) string {
sprint := func(args ...interface{}) string {
return fmt.Sprintf(colorString,
fmt.Sprint(args...))
}
return sprint
}
func main() {
arg := os.Args[1]
all := 0
err := filepath.Walk(arg, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if (!info.IsDir() && !strings.Contains(info.Name(), "test") ){
ext := filepath.Ext(path)
if ext == ".go" {
jj, _ := os.ReadFile(path)
g, _ := LineCounter(string(jj))
all += g
var u string
if g < 200 {
z := strconv.Itoa(g)
u = Info(z)
}
if g >= 200 && g < 1000 {
z := strconv.Itoa(g)
u = Warn(z)
}
if g >= 1000 {
z := strconv.Itoa(g)
u = Fata(z)
}
fmt.Printf("File %s have %s lines of code \n",path, u)
}
}
return nil
})
if err != nil {
log.Println(err)
}
fmt.Println("All lines", all)
}
func LineCounter(r string) (int, error) {
var count int
rr := strings.Split(r, "\n")
var rrr []string
cc := 0
comstart := false
for _, str := range rr {
if strings.HasPrefix(str, "/*") {
comstart = true
continue
}
if strings.Contains(str, "*/") {
comstart = false
cc += 1
}
if (str != "" && !strings.HasPrefix(str, "//") && !comstart) {
rrr = append(rrr, str)
}
}
count = len(rrr) - cc
return count, nil
}
I hope it will help some of you please tell me how it works