change project structure
This commit is contained in:
90
internal/output/output.go
Normal file
90
internal/output/output.go
Normal file
@ -0,0 +1,90 @@
|
||||
package output
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var (
|
||||
endOfLine string = "\n"
|
||||
devNull *log.Logger = log.New(ioutil.Discard, "", 0)
|
||||
stdout *log.Logger = log.New(os.Stdout, "", 0)
|
||||
stderr *log.Logger = log.New(os.Stderr, "", 0)
|
||||
verbose *log.Logger = devNull
|
||||
)
|
||||
|
||||
func SetQuiet(enabled bool) {
|
||||
if enabled {
|
||||
stdout = devNull
|
||||
stderr = devNull
|
||||
verbose = devNull
|
||||
}
|
||||
}
|
||||
|
||||
func SetVerbose(enabled bool) {
|
||||
if enabled {
|
||||
verbose = stderr
|
||||
} else {
|
||||
verbose = devNull
|
||||
}
|
||||
}
|
||||
|
||||
func SetEndOfLineNative() {
|
||||
switch os := runtime.GOOS; os {
|
||||
case "windows":
|
||||
setEndOfLineWindows()
|
||||
default:
|
||||
setEndOfLineUnix()
|
||||
}
|
||||
}
|
||||
|
||||
func EOL() string {
|
||||
return endOfLine
|
||||
}
|
||||
|
||||
func setEndOfLineUnix() {
|
||||
endOfLine = "\n"
|
||||
}
|
||||
|
||||
func setEndOfLineWindows() {
|
||||
endOfLine = "\r\n"
|
||||
}
|
||||
|
||||
func Print(v ...interface{}) {
|
||||
stdout.Print(v...)
|
||||
}
|
||||
|
||||
func Printf(format string, v ...interface{}) {
|
||||
stdout.Printf(format, v...)
|
||||
}
|
||||
|
||||
func Println(v ...interface{}) {
|
||||
stdout.Print(fmt.Sprint(v...) + endOfLine)
|
||||
}
|
||||
|
||||
func Error(v ...interface{}) {
|
||||
stderr.Print(v...)
|
||||
}
|
||||
|
||||
func Errorf(format string, v ...interface{}) {
|
||||
stderr.Printf(format, v...)
|
||||
}
|
||||
|
||||
func Errorln(v ...interface{}) {
|
||||
stderr.Print(fmt.Sprint(v...) + endOfLine)
|
||||
}
|
||||
|
||||
func Verbose(v ...interface{}) {
|
||||
verbose.Print(v...)
|
||||
}
|
||||
|
||||
func Verbosef(format string, v ...interface{}) {
|
||||
verbose.Printf(format, v...)
|
||||
}
|
||||
|
||||
func Verboseln(v ...interface{}) {
|
||||
verbose.Print(fmt.Sprint(v...) + endOfLine)
|
||||
}
|
26
internal/types/comment.go
Normal file
26
internal/types/comment.go
Normal file
@ -0,0 +1,26 @@
|
||||
package types
|
||||
|
||||
type Comment struct {
|
||||
Prefix string
|
||||
Value string
|
||||
}
|
||||
|
||||
func (obj *Comment) Full() string {
|
||||
return obj.Prefix + obj.Value
|
||||
}
|
||||
|
||||
func (obj *Comment) Line() string {
|
||||
return obj.Prefix + obj.Value
|
||||
}
|
||||
|
||||
func (obj *Comment) Fulln() string {
|
||||
return obj.Full() + endOfLine
|
||||
}
|
||||
|
||||
func (obj *Comment) Type() TElement {
|
||||
return TComment
|
||||
}
|
||||
|
||||
func (obj *Comment) Indent() string {
|
||||
return obj.Prefix
|
||||
}
|
50
internal/types/common.go
Normal file
50
internal/types/common.go
Normal file
@ -0,0 +1,50 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
)
|
||||
|
||||
type TElement int
|
||||
|
||||
const (
|
||||
TDeleted TElement = 0
|
||||
TComment TElement = 1
|
||||
TEmptyLine TElement = 2
|
||||
TKeyValue TElement = 3
|
||||
TSection TElement = 4
|
||||
TTrash TElement = 5
|
||||
)
|
||||
|
||||
var (
|
||||
endOfLine string = "\n"
|
||||
existing bool = false
|
||||
)
|
||||
|
||||
func SetEndOfLineNative() {
|
||||
switch os := runtime.GOOS; os {
|
||||
case "windows":
|
||||
SetEndOfLineWindows()
|
||||
default:
|
||||
SetEndOfLineUnix()
|
||||
}
|
||||
}
|
||||
|
||||
func SetEndOfLineUnix() {
|
||||
endOfLine = "\n"
|
||||
}
|
||||
|
||||
func SetEndOfLineWindows() {
|
||||
endOfLine = "\r\n"
|
||||
}
|
||||
|
||||
func SetExistingMode(value bool) {
|
||||
existing = value
|
||||
}
|
||||
|
||||
func createIfNotExist() bool {
|
||||
return !existing
|
||||
}
|
||||
|
||||
func failIfNotExist() bool {
|
||||
return existing
|
||||
}
|
24
internal/types/deleted.go
Normal file
24
internal/types/deleted.go
Normal file
@ -0,0 +1,24 @@
|
||||
package types
|
||||
|
||||
type Deleted struct {
|
||||
}
|
||||
|
||||
func (obj *Deleted) Full() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (obj *Deleted) Line() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (obj *Deleted) Fulln() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (obj *Deleted) Type() TElement {
|
||||
return TDeleted
|
||||
}
|
||||
|
||||
func (obj *Deleted) Indent() string {
|
||||
return ""
|
||||
}
|
9
internal/types/element.go
Normal file
9
internal/types/element.go
Normal file
@ -0,0 +1,9 @@
|
||||
package types
|
||||
|
||||
type Element interface {
|
||||
Full() string
|
||||
Fulln() string
|
||||
Line() string
|
||||
Indent() string
|
||||
Type() TElement
|
||||
}
|
25
internal/types/emptyline.go
Normal file
25
internal/types/emptyline.go
Normal file
@ -0,0 +1,25 @@
|
||||
package types
|
||||
|
||||
type EmptyLine struct {
|
||||
Prefix string
|
||||
}
|
||||
|
||||
func (obj *EmptyLine) Full() string {
|
||||
return obj.Prefix
|
||||
}
|
||||
|
||||
func (obj *EmptyLine) Line() string {
|
||||
return obj.Prefix
|
||||
}
|
||||
|
||||
func (obj *EmptyLine) Fulln() string {
|
||||
return obj.Full() + endOfLine
|
||||
}
|
||||
|
||||
func (obj *EmptyLine) Type() TElement {
|
||||
return TEmptyLine
|
||||
}
|
||||
|
||||
func (obj *EmptyLine) Indent() string {
|
||||
return obj.Prefix
|
||||
}
|
160
internal/types/ini.go
Normal file
160
internal/types/ini.go
Normal file
@ -0,0 +1,160 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Ini struct {
|
||||
Sections []Element
|
||||
}
|
||||
|
||||
func (obj *Ini) Init() {
|
||||
obj.Sections = append(obj.Sections, &Section{}) // global section
|
||||
}
|
||||
|
||||
func (obj *Ini) Full() string {
|
||||
var body strings.Builder
|
||||
for _, line := range obj.Sections {
|
||||
body.WriteString(line.Fulln())
|
||||
}
|
||||
return body.String()
|
||||
}
|
||||
|
||||
func (obj *Ini) FindSection(name string) (*Section, error) {
|
||||
for i, sect := range obj.Sections {
|
||||
if sect.(*Section).Name == name {
|
||||
return obj.Sections[i].(*Section), nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("Section not found: " + name)
|
||||
}
|
||||
|
||||
func (obj *Ini) DelSection(name string) error {
|
||||
gotIt := false
|
||||
for i, sect := range obj.Sections {
|
||||
if sect.Type() == TSection &&
|
||||
sect.(*Section).Name == name {
|
||||
obj.Sections[i] = &Deleted{}
|
||||
gotIt = true
|
||||
}
|
||||
}
|
||||
if gotIt {
|
||||
return nil
|
||||
} else if failIfNotExist() {
|
||||
return errors.New("Section not found: " + name)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (obj *Ini) Get() string {
|
||||
var sectList strings.Builder
|
||||
for _, sect := range obj.Sections {
|
||||
name := sect.(*Section).Name
|
||||
if name != "" || len(sect.(*Section).Lines) > 0 {
|
||||
sectList.WriteString(name + endOfLine)
|
||||
}
|
||||
}
|
||||
return strings.TrimSuffix(sectList.String(), endOfLine)
|
||||
}
|
||||
|
||||
func (obj *Ini) GetSection(section string) (string, error) {
|
||||
sect, err := obj.FindSection(section)
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
return sect.Full(), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (obj *Ini) GetKey(section, key string) (string, error) {
|
||||
sect, err := obj.FindSection(section)
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
return sect.GetKey(key)
|
||||
}
|
||||
}
|
||||
|
||||
func (obj *Ini) GetKeyVal(section, key, value string) error {
|
||||
sect, err := obj.FindSection(section)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
return sect.GetKeyVal(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
func (obj *Ini) AddSection(section string) *Section {
|
||||
sect, err := obj.FindSection(section)
|
||||
if err != nil {
|
||||
sectSize := len(obj.Sections)
|
||||
if sectSize > 1 {
|
||||
prevSect := obj.Sections[sectSize-1].(*Section)
|
||||
lineSize := len(prevSect.Lines)
|
||||
if lineSize == 0 || lineSize > 0 && prevSect.Lines[lineSize-1].Type() != TEmptyLine {
|
||||
obj.Sections[sectSize-1].(*Section).Lines = append(obj.Sections[sectSize-1].(*Section).Lines, &EmptyLine{})
|
||||
}
|
||||
}
|
||||
var newSection Section
|
||||
newSection.Name = section
|
||||
newSection.Prefix = obj.Sections[len(obj.Sections)-1].Indent()
|
||||
sect = &newSection
|
||||
obj.Sections = append(obj.Sections, sect)
|
||||
}
|
||||
return sect
|
||||
}
|
||||
|
||||
func (obj *Ini) SetSection(section string) *Section {
|
||||
return obj.AddSection(section)
|
||||
}
|
||||
|
||||
func (obj *Ini) AddKey(section, key, value string, reverse bool) error {
|
||||
sect, err := obj.FindSection(section)
|
||||
if err != nil {
|
||||
if createIfNotExist() {
|
||||
sect = obj.AddSection(section)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
sect.AddKey(key, value, reverse)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (obj *Ini) SetKey(section, key, value string) error {
|
||||
sect, err := obj.FindSection(section)
|
||||
if err != nil {
|
||||
if createIfNotExist() {
|
||||
sect = obj.AddSection(section)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return sect.SetKey(key, value)
|
||||
}
|
||||
|
||||
func (obj *Ini) DelKey(section, key string) error {
|
||||
sect, err := obj.FindSection(section)
|
||||
if err != nil {
|
||||
if failIfNotExist() {
|
||||
return err
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return sect.DelKey(key)
|
||||
}
|
||||
|
||||
func (obj *Ini) DelKeyVal(section, key, value string) error {
|
||||
sect, err := obj.FindSection(section)
|
||||
if err != nil {
|
||||
if failIfNotExist() {
|
||||
return err
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return sect.DelKeyVal(key, value)
|
||||
}
|
38
internal/types/keyvalue.go
Normal file
38
internal/types/keyvalue.go
Normal file
@ -0,0 +1,38 @@
|
||||
package types
|
||||
|
||||
type KeyValue struct {
|
||||
PrefixKey string
|
||||
Key string
|
||||
PostfixKey string
|
||||
PrefixValue string
|
||||
Value string
|
||||
PostfixValue string
|
||||
Comment Comment
|
||||
}
|
||||
|
||||
func (obj *KeyValue) Full() string {
|
||||
return obj.PrefixKey +
|
||||
obj.Key +
|
||||
obj.PostfixKey +
|
||||
"=" +
|
||||
obj.PrefixValue +
|
||||
obj.Value +
|
||||
obj.PostfixValue +
|
||||
obj.Comment.Full()
|
||||
}
|
||||
|
||||
func (obj *KeyValue) Line() string {
|
||||
return obj.Full()
|
||||
}
|
||||
|
||||
func (obj *KeyValue) Fulln() string {
|
||||
return obj.Full() + endOfLine
|
||||
}
|
||||
|
||||
func (obj *KeyValue) Type() TElement {
|
||||
return TKeyValue
|
||||
}
|
||||
|
||||
func (obj *KeyValue) Indent() string {
|
||||
return obj.PrefixKey
|
||||
}
|
200
internal/types/section.go
Normal file
200
internal/types/section.go
Normal file
@ -0,0 +1,200 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Section struct {
|
||||
Prefix string
|
||||
Name string
|
||||
Postfix string
|
||||
Comment Comment
|
||||
Lines []Element
|
||||
}
|
||||
|
||||
func (obj *Section) Headern() string {
|
||||
if obj.Name == "" {
|
||||
return ""
|
||||
} else {
|
||||
return obj.Prefix + "[" + obj.Name + "]" + obj.Postfix + obj.Comment.Full() + endOfLine
|
||||
}
|
||||
}
|
||||
|
||||
func (obj *Section) Line() string {
|
||||
return obj.Header()
|
||||
}
|
||||
|
||||
func (obj *Section) Header() string {
|
||||
return strings.TrimSuffix(obj.Headern(), endOfLine)
|
||||
}
|
||||
|
||||
func (obj *Section) Fulln() string {
|
||||
var body strings.Builder
|
||||
for _, line := range obj.Lines {
|
||||
body.WriteString(line.Fulln())
|
||||
}
|
||||
return obj.Headern() + body.String()
|
||||
}
|
||||
|
||||
func (obj *Section) Full() string {
|
||||
return strings.TrimSuffix(obj.Fulln(), endOfLine)
|
||||
}
|
||||
|
||||
func (obj *Section) Type() TElement {
|
||||
return TSection
|
||||
}
|
||||
|
||||
func (obj *Section) Indent() string {
|
||||
return obj.Prefix
|
||||
}
|
||||
|
||||
func (obj *Section) DelKey(name string) error {
|
||||
gotIt := false
|
||||
for i, keyVal := range obj.Lines {
|
||||
if keyVal.Type() == TKeyValue &&
|
||||
keyVal.(*KeyValue).Key == name {
|
||||
obj.Lines[i] = &Deleted{}
|
||||
gotIt = true
|
||||
}
|
||||
}
|
||||
if gotIt {
|
||||
return nil
|
||||
} else if failIfNotExist() {
|
||||
return errors.New("Parameter not found: " + name)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (obj *Section) DelKeyVal(name, value string) error {
|
||||
gotIt := false
|
||||
for i, keyVal := range obj.Lines {
|
||||
if keyVal.Type() == TKeyValue &&
|
||||
keyVal.(*KeyValue).Key == name &&
|
||||
keyVal.(*KeyValue).Value == value {
|
||||
obj.Lines[i] = &Deleted{}
|
||||
gotIt = true
|
||||
}
|
||||
}
|
||||
if gotIt {
|
||||
return nil
|
||||
} else if failIfNotExist() {
|
||||
return errors.New("Parameter:value pair not found: " + name + ":" + value)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (obj *Section) GetKey(name string) (string, error) {
|
||||
var err error = nil
|
||||
var result strings.Builder
|
||||
for _, keyVal := range obj.Lines {
|
||||
if keyVal.Type() == TKeyValue && keyVal.(*KeyValue).Key == name {
|
||||
result.WriteString(keyVal.(*KeyValue).Value + endOfLine)
|
||||
}
|
||||
}
|
||||
if result.String() == "" {
|
||||
err = errors.New("Parameter not found: " + name)
|
||||
}
|
||||
return strings.TrimSuffix(result.String(), endOfLine), err
|
||||
}
|
||||
|
||||
func (obj *Section) GetKeyVal(name, value string) error {
|
||||
for _, keyVal := range obj.Lines {
|
||||
if keyVal.Type() == TKeyValue &&
|
||||
keyVal.(*KeyValue).Key == name &&
|
||||
keyVal.(*KeyValue).Value == value {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.New("Parameter:Value not found: " + name + ":" + value)
|
||||
}
|
||||
|
||||
func (obj *Section) appendKey(name, value string, reverse bool) {
|
||||
var newKeyValue KeyValue
|
||||
var replaceIndex int = -1
|
||||
newKeyValue.Key = name
|
||||
newKeyValue.Value = value
|
||||
if reverse {
|
||||
// for right indent and tabs
|
||||
for i := 0; i < len(obj.Lines); i++ {
|
||||
if obj.Lines[i].Type() == TKeyValue {
|
||||
template := obj.Lines[i].(*KeyValue)
|
||||
newKeyValue.PrefixKey = template.PrefixKey
|
||||
newKeyValue.PostfixKey = template.PostfixKey
|
||||
newKeyValue.PrefixValue = template.PrefixValue
|
||||
newKeyValue.PostfixValue = template.PostfixValue
|
||||
break
|
||||
}
|
||||
}
|
||||
obj.Lines = append([]Element{&newKeyValue}, obj.Lines...)
|
||||
} else {
|
||||
// replace first emptyline
|
||||
for i := len(obj.Lines) - 1; i >= 0; i-- {
|
||||
if obj.Lines[i].Type() == TEmptyLine {
|
||||
replaceIndex = i
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
// for right indent and tabs
|
||||
for i := len(obj.Lines) - 1; i >= 0; i-- {
|
||||
if obj.Lines[i].Type() == TKeyValue {
|
||||
template := obj.Lines[i].(*KeyValue)
|
||||
newKeyValue.PrefixKey = template.PrefixKey
|
||||
newKeyValue.PostfixKey = template.PostfixKey
|
||||
newKeyValue.PrefixValue = template.PrefixValue
|
||||
newKeyValue.PostfixValue = template.PostfixValue
|
||||
break
|
||||
}
|
||||
}
|
||||
if replaceIndex == -1 {
|
||||
obj.Lines = append(obj.Lines, &newKeyValue)
|
||||
} else {
|
||||
obj.Lines = append(obj.Lines, obj.Lines[replaceIndex])
|
||||
obj.Lines[replaceIndex] = &newKeyValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (obj *Section) AddKey(name, value string, reverse bool) {
|
||||
gotIt := false
|
||||
for i, keyVal := range obj.Lines {
|
||||
if keyVal.Type() == TKeyValue &&
|
||||
keyVal.(*KeyValue).Key == name &&
|
||||
keyVal.(*KeyValue).Value == value {
|
||||
if !gotIt {
|
||||
gotIt = true
|
||||
} else {
|
||||
obj.Lines[i] = &Deleted{}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !gotIt {
|
||||
obj.appendKey(name, value, reverse)
|
||||
}
|
||||
}
|
||||
|
||||
func (obj *Section) SetKey(name, value string) error {
|
||||
gotIt := false
|
||||
for i, keyVal := range obj.Lines {
|
||||
if keyVal.Type() == TKeyValue &&
|
||||
keyVal.(*KeyValue).Key == name {
|
||||
if !gotIt {
|
||||
keyVal.(*KeyValue).Value = value
|
||||
gotIt = true
|
||||
} else {
|
||||
obj.Lines[i] = &Deleted{}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !gotIt {
|
||||
if createIfNotExist() {
|
||||
obj.appendKey(name, value, false)
|
||||
} else {
|
||||
return errors.New("Parameter not found: " + name)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
25
internal/types/trash.go
Normal file
25
internal/types/trash.go
Normal file
@ -0,0 +1,25 @@
|
||||
package types
|
||||
|
||||
type Trash struct {
|
||||
Value string
|
||||
}
|
||||
|
||||
func (obj *Trash) Full() string {
|
||||
return obj.Value
|
||||
}
|
||||
|
||||
func (obj *Trash) Line() string {
|
||||
return obj.Value
|
||||
}
|
||||
|
||||
func (obj *Trash) Fulln() string {
|
||||
return obj.Full() + endOfLine
|
||||
}
|
||||
|
||||
func (obj *Trash) Type() TElement {
|
||||
return TTrash
|
||||
}
|
||||
|
||||
func (obj *Trash) Indent() string {
|
||||
return ""
|
||||
}
|
Reference in New Issue
Block a user