You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
naza/pkg/filebatch/filebatch.go

132 lines
3.1 KiB
Go

// Copyright 2019, Chef. All rights reserved.
// https://github.com/q191201771/naza
//
// Use of this source code is governed by a MIT-style license
// that can be found in the License file.
//
// Author: Chef (191201771@qq.com)
package filebatch
import (
"bytes"
"errors"
"io/ioutil"
"os"
"path/filepath"
"strings"
)
// @param path 带路径的文件名
// @param info 文件的 os.FileInfo 信息
// @param content 文件内容
// @return 返回nil或者content原始内容则不修改文件内容返回其他内容则会覆盖重写文件
type WalkFunc func(path string, info os.FileInfo, content []byte, err error) []byte
// 遍历访问指定文件夹下的文件
// @param root 需要遍历访问的文件夹
// @param recursive 是否递归访问子文件夹
// @param suffix 指定文件名后缀进行过滤,如果为"",则不过滤
func Walk(root string, recursive bool, suffix string, walkFn WalkFunc) error {
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil {
walkFn(path, info, nil, err)
return nil
}
if !recursive && info.IsDir() && path != root {
return filepath.SkipDir
}
if info.IsDir() {
return nil
}
if suffix != "" && !strings.HasSuffix(info.Name(), suffix) {
return nil
}
content, err := ioutil.ReadFile(path)
if err != nil {
walkFn(path, info, content, err)
return nil
}
newContent := walkFn(path, info, content, nil)
if newContent != nil && bytes.Compare(content, newContent) != 0 {
if err = ioutil.WriteFile(path, newContent, 0755); err != nil {
return err
}
}
return nil
})
return err
}
// 文件尾部添加内容
func AddTailContent(content []byte, tail []byte) []byte {
if !bytes.HasSuffix(content, []byte{'\n'}) {
content = append(content, '\n')
}
return append(content, tail...)
}
// 文件头部添加内容
func AddHeadContent(content []byte, head []byte) []byte {
if !bytes.HasSuffix(head, []byte{'\n'}) {
head = append(head, '\n')
}
return append(head, content...)
}
// 行号范围
// 1表示首行-1表示最后一行
type LineRange struct {
From int
To int
}
var ErrLineRange = errors.New("naza.filebatch: line range error")
func calcLineRange(len int, lr LineRange) (LineRange, error) {
// 换算成从0开始的下标
if lr.From < 0 {
lr.From = len + lr.From
} else if lr.From > 0 {
lr.From = lr.From - 1
} else {
return lr, ErrLineRange
}
if lr.To < 0 {
lr.To = len + lr.To
} else if lr.To > 0 {
lr.To = lr.To - 1
} else {
return lr, ErrLineRange
}
// 排序交换
if lr.From > lr.To {
lr.From, lr.To = lr.To, lr.From
}
if lr.From < 0 || lr.From >= len || lr.To < 0 || lr.To >= len {
return lr, ErrLineRange
}
return lr, nil
}
func DeleteLines(content []byte, lr LineRange) ([]byte, error) {
lines := bytes.Split(content, []byte{'\n'})
length := len(lines)
nlr, err := calcLineRange(length, lr)
if err != nil {
return content, err
}
var nlines [][]byte
if nlr.From > 0 {
nlines = append(nlines, lines[:nlr.From]...)
}
if nlr.To < length-1 {
nlines = append(nlines, lines[nlr.To+1:]...)
}
return bytes.Join(nlines, []byte{'\n'}), nil
}