统计代码行数工具 用golang实现

首先:修改conf文件,配置要查找什么后缀的文件代码行数

使用方法:countcodeliine filename or nothing(计算可执行程序所在目录)


实现功能

1,统计代码行数

2,可以根据配置文件(conf)来进行设置要对什么类型的代码进行统计

3,统计每个类型文件行数,和总行数


将来要实现功能

1,注释行数

2,注释率

3,导出csv功能


代码

package main

import(
	"os"
	"container/list"
	"io"
	"log"
	"path/filepath"
	"bufio"
)

func init(){
	log.SetFlags(log.Llongfile| log.LstdFlags)
}

func main(){
	conf,err := ParseConf()
	if nil != err{
		log.Println(err)
		return
	}
	allFiles := GetAllFilesName()
	srcList := GetParsedFilesByConf(allFiles,conf)
	res := Parse(srcList)
	total := 0
	for k,v := range res{
		total += v
		println(k,":",v)
	}
	println("Total: ",total)
}

//example:map["go" or "css"]123
func Parse(files list.List)(parseResult map[string]int){
	parseResult = map[string]int{}
	for e := files.Front(); nil != e; e = e.Next(){
		v := e.Value.(string)
		ext := filepath.Ext(v)
		parseResult[ext] += ComputeLine(v)
	}
	return
}

func ComputeLine(path string)(num int){
	f,err := os.Open(path)
	if nil != err{
		log.Println(err)
		return
	}
	defer f.Close()

	r := bufio.NewReader(f)
	for{
		_,err := r.ReadString('\n')
		if io.EOF == err || nil != err{
			break
		}
		num += 1
	}
	return
}

func ParseConf()(conf []string,err error){
	confPath,_ := os.Getwd()
	confPath +=  "/conf"
	file,err := os.Open(confPath)
	if nil != err{
		log.Println(err)
		return
	}
	defer file.Close()
		scanner := bufio.NewScanner(file)
	for scanner.Scan(){
		conf = append(conf,scanner.Text())
	}
	//log.Println(conf)
	return
}

func GetSrcFullPath()(fullPath string){
	args := os.Args;
	parameterLen := len(args)
	if parameterLen == 1{
		fullPath,_ = os.Getwd()
	}else if(parameterLen >= 2){
		fullPath = args[1]
	}

	fullPath,_ = filepath.Abs(fullPath)
	return
}

func GetParsedFilesByConf(lst list.List,conf []string)(l list.List){
	for e := lst.Front(); nil != e; e = e.Next(){
		ext := filepath.Ext(e.Value.(string))
		for _,extension := range conf{
			if ext == extension{
				l.PushBack(e.Value.(string))
				continue
			}
		}
	}

	for e := l.Front(); nil != e; e = e.Next(){
		println("matched string:",e.Value.(string))
	}
	return
}

func GetAllFilesName() (lst list.List){
	fullPath := GetSrcFullPath()
	filepath.Walk(fullPath,func(path string,fi os.FileInfo,err error)error{
		if nil == fi {
			return err
		}
		if fi.IsDir() {
			return nil
		}

		//println(fi.Name())
		//println(path)
		//name := fi.Name()
		lst.PushBack(path)
		return nil
	})
	return
}

rd := bufio.NewReader(file)
	var line string
	for{
		line,err = rd.ReadString('\n')
		if io.EOF == err{
			err = nil
			break
		}else if nil != err{
			break
		}
		conf = append(conf,line[:len(line)-1])
	}
ReadString('\n')只能在linux上可以运行,因为windwos换行符是\r\n,linux是\n,所以换成用Scan来实现,但是Scan是go1.1

新增的struct,大家使用时请务必注意升级go。

conf配置文件

.go
.html
.css
.js

github地址:

https://github.com/zoro-du/countcodeline

欢迎大家随便修改

相关文章

程序目录结构 简单实现,用户登录后返回一个jwt的token,下次请求带上token请求用户信息接口并返回信息...
本篇博客的主要内容是用go写一个简单的Proof-of-Work共识机制,不涉及到网络通信环节,只是一个本地的简...
简介 默克尔树(MerkleTree)是一种典型的二叉树结构,其主要特点为: 最下面的叶节点包含存储数据或其...
接下来学习并发编程, 并发编程是go语言最有特色的地方, go对并发编程是原生支持. goroutine是go中最近本...
先普及一下, 什么是广度优先搜索 广度优先搜索类似于树的层次遍历。从图中的某一顶点出发,遍历每一个顶...
第一天: 接口的定义和实现 第二天: 一. go语言是面向接口编程. 在学习继承的时候说过, go语言只有封装,...