10 Commits
0.2.3 ... 0.4.0

Author SHA1 Message Date
c258e6096f refactor: improved line parser
- improved support for C-style comments;
- add support for keys with square brackets;
- slightly improved speed.
2020-11-09 17:03:57 +03:00
a5976526ae add spec for src.rpm 2020-11-03 18:26:45 +03:00
3d467bd979 Merge branch 'master' of https://github.com/GenZmeY/multini 2020-11-03 17:36:28 +03:00
28fe0bda17 update .gitignore 2020-11-03 17:36:03 +03:00
25f6b1537d Create README.md 2020-11-03 17:29:09 +03:00
287547b69e add github actions workflow 2020-11-03 17:11:59 +03:00
f4934225b6 Ah shit, here we go again 2020-11-03 13:14:35 +03:00
69be8312f8 add C-style comment support 2020-11-03 11:20:24 +03:00
f083dcd3d8 enable go modules 2020-11-03 11:19:37 +03:00
44e955a047 change project structure 2020-11-03 10:47:19 +03:00
69 changed files with 324 additions and 100 deletions

118
.github/workflows/binary-release.yml vendored Normal file
View File

@ -0,0 +1,118 @@
name: binary release
on:
push:
tags:
- '[0-9]+.[0-9]+.[0-9]+'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Get the version
id: get_version
run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3)
- name: checkout
uses: actions/checkout@v2
- name: Setup Go
uses: actions/setup-go@v2
with:
go-version: '1.13.0'
- name: Build
run: make -j $(nproc) compile VERSION=${{ steps.get_version.outputs.VERSION }}
- name: create release
id: create_release
uses: actions/create-release@latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.get_version.outputs.VERSION }}
release_name: Release ${{ steps.get_version.outputs.VERSION }}
draft: false
prerelease: false
- name: darwin-386
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./bin/${{ github.event.repository.name }}-darwin-386
asset_name: ${{ github.event.repository.name }}-darwin-386
asset_content_type: application/octet-stream
- name: darwin-amd64
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./bin/${{ github.event.repository.name }}-darwin-amd64
asset_name: ${{ github.event.repository.name }}-darwin-amd64
asset_content_type: application/octet-stream
- name: freebsd-386
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./bin/${{ github.event.repository.name }}-freebsd-386
asset_name: ${{ github.event.repository.name }}-freebsd-386
asset_content_type: application/octet-stream
- name: freebsd-amd64
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./bin/${{ github.event.repository.name }}-freebsd-amd64
asset_name: ${{ github.event.repository.name }}-freebsd-amd64
asset_content_type: application/octet-stream
- name: linux-386
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./bin/${{ github.event.repository.name }}-linux-386
asset_name: ${{ github.event.repository.name }}-linux-386
asset_content_type: application/octet-stream
- name: linux-amd64
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./bin/${{ github.event.repository.name }}-linux-amd64
asset_name: ${{ github.event.repository.name }}-linux-amd64
asset_content_type: application/octet-stream
- name: windows-386
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./bin/${{ github.event.repository.name }}-windows-386.exe
asset_name: ${{ github.event.repository.name }}-windows-386.exe
asset_content_type: application/octet-stream
- name: windows-amd64
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./bin/${{ github.event.repository.name }}-windows-amd64.exe
asset_name: ${{ github.event.repository.name }}-windows-amd64.exe
asset_content_type: application/octet-stream

23
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,23 @@
name: build
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
- name: Setup Go
uses: actions/setup-go@v2
with:
go-version: '1.13.0'
- name: Build
run: make -j $(nproc)

23
.gitignore vendored
View File

@ -1,20 +1,3 @@
# Binaries for programs and plugins /bin/
bin/* /test/data/out_ini/
multini /cmd/multini/multini
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Custom binary test
tests/out_ini/*
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/

View File

@ -1,21 +1,30 @@
NAME=multini NAME = multini
VERSION=0.2.3 VERSION = dev_$(shell date +%F_%T)
GOCMD=go GOCMD = go
LDFLAGS:="$(LDFLAGS) -X 'main.Version=$(VERSION)'" LDFLAGS := "$(LDFLAGS) -X 'main.Version=$(VERSION)'"
GOBUILD=$(GOCMD) build -ldflags=$(LDFLAGS) GOBUILD = $(GOCMD) build -ldflags=$(LDFLAGS)
SRCMAIN=. SRCMAIN = ./cmd/$(NAME)
BINDIR=bin SRCDOC = ./doc
BIN=$(BINDIR)/$(NAME) SRCTEST = ./test
README=README BINDIR = bin
LICENSE=LICENSE BIN = $(BINDIR)/$(NAME)
TEST=./run_test.sh README = $(SRCDOC)/README
PREFIX=/usr LICENSE = LICENSE
TEST = $(SRCTEST)/run_test.sh
PREFIX = /usr
.PHONY: all prep doc build check-build freebsd-386 darwin-386 linux-386 windows-386 freebsd-amd64 darwin-amd64 linux-amd64 windows-amd64 compile install check-install uninstall clean test
all: build all: build
prep: clean prep: clean
go mod init; go mod tidy
mkdir $(BINDIR) mkdir $(BINDIR)
doc: check-build
test -d $(SRCDOC) || mkdir $(SRCDOC)
$(BIN) --help > $(README)
build: prep build: prep
$(GOBUILD) -o $(BIN) $(SRCMAIN) $(GOBUILD) -o $(BIN) $(SRCMAIN)
@ -48,7 +57,7 @@ windows-amd64: prep
compile: freebsd-386 darwin-386 linux-386 windows-386 freebsd-amd64 darwin-amd64 linux-amd64 windows-amd64 compile: freebsd-386 darwin-386 linux-386 windows-386 freebsd-amd64 darwin-amd64 linux-amd64 windows-amd64
install: check-build install: check-build doc
install -m 755 -d $(PREFIX)/bin/ install -m 755 -d $(PREFIX)/bin/
install -m 755 $(BIN) $(PREFIX)/bin/ install -m 755 $(BIN) $(PREFIX)/bin/
install -m 755 -d $(PREFIX)/share/licenses/$(NAME)/ install -m 755 -d $(PREFIX)/share/licenses/$(NAME)/
@ -71,3 +80,4 @@ clean:
test: check-build test: check-build
$(TEST) $(BIN) $(TEST) $(BIN)

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# multini
it's like crudini but for ini files with duplicate parameter names

View File

@ -1,8 +1,8 @@
package main package main
import ( import (
"multini/output" "multini/internal/output"
"multini/types" "multini/internal/types"
) )
func chk() int { func chk() int {

View File

@ -4,8 +4,8 @@ import (
"errors" "errors"
"os" "os"
"multini/output" "multini/internal/output"
"multini/types" "multini/internal/types"
"github.com/juju/gnuflag" "github.com/juju/gnuflag"
) )

View File

@ -3,8 +3,8 @@ package main
import ( import (
"os" "os"
"multini/output" "multini/internal/output"
"multini/types" "multini/internal/types"
) )
const ( const (

View File

@ -7,49 +7,103 @@ import (
"regexp" "regexp"
"strings" "strings"
"multini/output" "multini/internal/output"
"multini/types" "multini/internal/types"
) )
var ( var (
// Ng - Named Group // Ng - Named Group
NgPrefix string = `prefix` NgPrefix string = `prefix`
NgPostifx string = `postfix` NgPostifx string = `postfix`
NgSection string = `section` NgSection string = `section`
NgKey string = `key` NgKey string = `key`
NgKeyPostfix string = `key_postfix` NgKeyPostfix string = `key_postfix`
NgValue string = `value` NgValue string = `value`
NgValuePrefix string = `value_prefix` NgValuePrefix string = `value_prefix`
NgValuePostfix string = `value_postfix` NgValuePostfix string = `value_postfix`
NgComment string = `comment` NgComment string = `comment`
NgCommentPrefix string = `comment_prefix` NgData string = `data`
RxBodyPrefix string = `(?P<` + NgPrefix + `>\s+)?` RxEmpty string = `^(?P<` + NgPrefix + `>\s+)?$`
RxSectionName string = `\[(?P<` + NgSection + `>.+)\]` RxSection string = `^(?P<` + NgPrefix + `>\s+)?\[(?P<` + NgSection + `>[^\]]+)\](?P<` + NgPostifx + `>\s+)?$`
RxKey string = `(?P<` + NgKey + `>(?:[^;#=]+[^\s=;#]|[^;#=]))?` RxKey string = `^(?P<` + NgPrefix + `>\s+)?(?P<` + NgKey + `>.*[^\s]+)(?P<` + NgKeyPostfix + `>\s+)?$`
RxKeyPostfix string = `(?P<` + NgKeyPostfix + `>\s+)?` RxValue string = `^(?P<` + NgValuePrefix + `>\s+)?(?P<` + NgValue + `>.*[^\s])(?P<` + NgValuePostfix + `>\s+)?$`
RxValuePrefix string = `(?P<` + NgValuePrefix + `>\s+)?`
RxValue string = `(?P<` + NgValue + `>(?:[^;#]+[^\s;#]|[^;#]))?` RxEmptyCompile *regexp.Regexp = regexp.MustCompile(RxEmpty)
RxValuePostfix string = `(?P<` + NgValuePostfix + `>\s+)?` RxSectionCompile *regexp.Regexp = regexp.MustCompile(RxSection)
RxKeyVal string = RxKey + RxKeyPostfix + `=` + RxValuePrefix + RxValue + RxValuePostfix RxKeyCompile *regexp.Regexp = regexp.MustCompile(RxKey)
RxBody string = `(?:` + RxSectionName + `|` + RxKeyVal + `)?` RxValueCompile *regexp.Regexp = regexp.MustCompile(RxValue)
RxBodyPostfix string = `(?P<` + NgPostifx + `>\s+)?`
RxCommentPrefix string = `(?P<` + NgCommentPrefix + `>[#;]\s*)`
RxCommentText string = `(?P<` + NgComment + `>.+)?`
RxComment string = `(?:` + RxCommentPrefix + RxCommentText + `)?`
Rx string = RxBodyPrefix + RxBody + RxBodyPostfix + RxComment
RxCompiled *regexp.Regexp = regexp.MustCompile(Rx)
) )
func rxParse(rx *regexp.Regexp, str string) map[string]string { func parse(str string) map[string]string {
match := rx.FindStringSubmatch(str) var result map[string]string = make(map[string]string)
result := make(map[string]string) var data string
for i, name := range rx.SubexpNames() {
data, result[NgComment] = getDataComment(str)
if data != "" {
findNamedGroups(data, RxEmptyCompile, &result)
}
if result[NgPrefix] != "" {
return result
}
findNamedGroups(data, RxSectionCompile, &result)
if result[NgSection] == "" && data != "" {
keyPart, valPart := getKeyValue(data)
findNamedGroups(keyPart, RxKeyCompile, &result)
findNamedGroups(valPart, RxValueCompile, &result)
}
return result
}
func findNamedGroups(str string, Rx *regexp.Regexp, result *map[string]string) {
match := Rx.FindStringSubmatch(str)
for i, name := range Rx.SubexpNames() {
if i != 0 && name != "" && i <= len(match) { if i != 0 && name != "" && i <= len(match) {
result[name] = match[i] (*result)[name] = match[i]
} }
} }
return result }
func getDataComment(str string) (string, string) {
var indexes []int
var commentIndex int = -1
indexes = append(indexes, strings.Index(str, "//"))
indexes = append(indexes, strings.Index(str, "#"))
indexes = append(indexes, strings.Index(str, ";"))
for _, index := range indexes {
if commentIndex == -1 {
if index != -1 {
commentIndex = index
}
} else {
if index != -1 {
if commentIndex > index {
commentIndex = index
}
}
}
}
if commentIndex == -1 {
return str, ""
} else {
return str[:commentIndex], str[commentIndex:]
}
}
func getKeyValue(data string) (string, string) {
index := strings.Index(data, "=")
if index != -1 {
return data[:index], data[index+1:]
}
return "", ""
} }
func debugMap(el map[string]string) string { func debugMap(el map[string]string) string {
@ -61,14 +115,14 @@ func debugMap(el map[string]string) string {
} }
func appendLine(ini *types.Ini, line string) error { func appendLine(ini *types.Ini, line string) error {
elements := rxParse(RxCompiled, line) // elements := rxParse(line)
elements := parse(line)
switch { switch {
case elements[NgSection] != "": case elements[NgSection] != "":
var newSection types.Section var newSection types.Section
newSection.Name = elements[NgSection] newSection.Name = elements[NgSection]
newSection.Prefix = elements[NgPrefix] newSection.Prefix = elements[NgPrefix]
newSection.Postfix = elements[NgPostifx] newSection.Postfix = elements[NgPostifx]
newSection.Comment.Prefix = elements[NgCommentPrefix]
newSection.Comment.Value = elements[NgComment] newSection.Comment.Value = elements[NgComment]
if newSection.Line() == line { if newSection.Line() == line {
ini.Sections = append(ini.Sections, &newSection) ini.Sections = append(ini.Sections, &newSection)
@ -87,7 +141,6 @@ func appendLine(ini *types.Ini, line string) error {
newKeyValue.PrefixValue = elements[NgValuePrefix] newKeyValue.PrefixValue = elements[NgValuePrefix]
newKeyValue.PostfixValue = elements[NgValuePostfix] newKeyValue.PostfixValue = elements[NgValuePostfix]
newKeyValue.Comment.Value = elements[NgComment] newKeyValue.Comment.Value = elements[NgComment]
newKeyValue.Comment.Prefix = elements[NgCommentPrefix]
if newKeyValue.Line() == line { if newKeyValue.Line() == line {
ini.Sections[len(ini.Sections)-1].(*types.Section).Lines = append(ini.Sections[len(ini.Sections)-1].(*types.Section).Lines, &newKeyValue) ini.Sections[len(ini.Sections)-1].(*types.Section).Lines = append(ini.Sections[len(ini.Sections)-1].(*types.Section).Lines, &newKeyValue)
return nil return nil
@ -98,8 +151,8 @@ func appendLine(ini *types.Ini, line string) error {
} }
case elements[NgComment] != "": case elements[NgComment] != "":
var newComment types.Comment var newComment types.Comment
newComment.Prefix = elements[NgPrefix] + elements[NgCommentPrefix]
newComment.Value = elements[NgComment] newComment.Value = elements[NgComment]
newComment.Prefix = elements[NgPrefix]
if newComment.Line() == line { if newComment.Line() == line {
ini.Sections[len(ini.Sections)-1].(*types.Section).Lines = append(ini.Sections[len(ini.Sections)-1].(*types.Section).Lines, &newComment) ini.Sections[len(ini.Sections)-1].(*types.Section).Lines = append(ini.Sections[len(ini.Sections)-1].(*types.Section).Lines, &newComment)
return nil return nil

View File

@ -7,7 +7,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"multini/types" "multini/internal/types"
) )
// Source: https://gist.github.com/var23rav/23ae5d0d4d830aff886c3c970b8f6c6b // Source: https://gist.github.com/var23rav/23ae5d0d4d830aff886c3c970b8f6c6b

View File

5
go.mod Normal file
View File

@ -0,0 +1,5 @@
module multini
go 1.13
require github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d

2
go.sum Normal file
View File

@ -0,0 +1,2 @@
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d h1:c93kUJDtVAXFEhsCh5jSxyOJmFHuzcihnslQiX8Urwo=
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=

View File

@ -1,6 +1,6 @@
# comment # comment
; comment again ; comment again
// comment with indent
DefKey1 = Some Value1 DefKey1 = Some Value1
DefKey2 = Some Value2 And Tabs! # With Comment DefKey2 = Some Value2 And Tabs! # With Comment
DefKey3=NoSpaces! DefKey3=NoSpaces!
@ -10,7 +10,7 @@ DefKey3=NoSpaces!
Key2 = 2 Key2 = 2
Key3 = 3 Key3 = 3
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = 1 Key = 1
Key = 2 Key = 2
Key = 3 Key = 3

View File

@ -9,7 +9,7 @@ DefKey3=NoSpaces!
Key1 = 1 Key1 = 1
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = 1 Key = 1
Key = 2 Key = 2
Key = 3 Key = 3

View File

@ -9,7 +9,7 @@ DefKey3=NoSpaces!
Key1 = 1 Key1 = 1
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = 1 Key = 1
Key = 2 Key = 2
Key = 3 Key = 3

View File

@ -8,7 +8,7 @@ DefKey3=NoSpaces!
[SimpleSection] # Comment For Section [SimpleSection] # Comment For Section
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = 1 Key = 1
Key = 2 Key = 2
Key = 3 Key = 3

View File

@ -9,7 +9,7 @@ DefKey3=NoSpaces!
Key1 = 1 Key1 = 1
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
[SectionWithIndent] [SectionWithIndent]
Key=Value Key=Value

View File

@ -9,7 +9,7 @@ DefKey3=NoSpaces!
Key1 = 1 Key1 = 1
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = 1 Key = 1
Key = 3 Key = 3

View File

@ -9,7 +9,7 @@ DefKey3=NoSpaces!
Key1 = 1 Key1 = 1
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = 1 Key = 1
Key = 2 Key = 2
Key = 3 Key = 3

View File

@ -0,0 +1 @@
skip/skip

View File

@ -9,7 +9,7 @@ DefKey3=NoSpaces!
Key1 = 1 Key1 = 1
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = onlyone Key = onlyone
[SectionWithIndent] [SectionWithIndent]

View File

@ -1,6 +1,6 @@
# comment # comment
; comment again ; comment again
// comment with indent
DefKey1 = Some Value1 DefKey1 = Some Value1
DefKey2 = Some Value2 And Tabs! # With Comment DefKey2 = Some Value2 And Tabs! # With Comment
DefKey3=NoSpaces! DefKey3=NoSpaces!
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
Key1 = 1 Key1 = 1
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = 1 Key = 1
Key = 2 Key = 2
Key = 3 Key = 3

View File

@ -9,7 +9,7 @@ DefKey3=NoSpaces!
Key1 = 1 Key1 = 1
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = 1 Key = 1
Key = 2 Key = 2
Key = 3 Key = 3

View File

@ -9,7 +9,7 @@ DefKey3=NoSpaces!
Key1 = 1 Key1 = 1
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = 1 Key = 1
Key = 2 Key = 2
Key = 3 Key = 3

View File

@ -9,7 +9,7 @@ DefKey3=NoSpaces!
Key1 = 1 Key1 = 1
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = 1 Key = 1
Key = 2 Key = 2
Key = 3 Key = 3

View File

@ -9,7 +9,7 @@ DefKey3=NoSpaces!
Key1 = 1 Key1 = 1
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = 1 Key = 1
Key = 2 Key = 2
Key = 3 Key = 3

View File

@ -9,7 +9,7 @@ DefKey3=NoSpaces!
Key1 = 1 Key1 = 1
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = 1 Key = 1
Key = 2 Key = 2
Key = 3 Key = 3

View File

@ -9,7 +9,7 @@ DefKey3=NoSpaces!
Key1 = 1 Key1 = 1
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = 1 Key = 1
Key = 2 Key = 2
Key = 3 Key = 3

View File

@ -9,7 +9,7 @@ DefKey3=NoSpaces!
Key1 = 1 Key1 = 1
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = 1 Key = 1
Key = 2 Key = 2
Key = 3 Key = 3

View File

@ -9,7 +9,7 @@ DefKey3=NoSpaces!
Key1 = 1 Key1 = 1
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = 1 Key = 1
Key = 2 Key = 2
Key = 3 Key = 3

View File

@ -0,0 +1,19 @@
# comment
; comment again
DefKey1 = Some Value1
DefKey2 = Some Value2 And Tabs! # With Comment
DefKey3=NoSpaces!
[Slashes/Test] // Comment For Section
./Dir1/File = skip/skip // comment
Key2 = 2
[MultipleKeySection] // C style comment
Key = 1
Key = 2
Key = 3
[SectionWithIndent]
Key=Value
[SectionWithoutNewLineBefore]

View File

@ -9,7 +9,7 @@ DefKey3=NoSpaces!
Key1 = 1 Key1 = 1
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = 1 Key = 1
Key = 2 Key = 2
Key = 3 Key = 3

View File

@ -9,7 +9,7 @@ DefKey3=NoSpaces!
Key1 = 1 Key1 = 1
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = 1 Key = 1
Key = 2 Key = 2
Key = 3 Key = 3

View File

@ -9,7 +9,7 @@ DefKey3=NoSpaces!
Key1 = 1 Key1 = 1
Key2 = 2 Key2 = 2
[MultipleKeySection] [MultipleKeySection] // C style comment
Key = 1 Key = 1
Key = 2 Key = 2
Key = 3 Key = 3

View File

@ -0,0 +1,7 @@
#!/bin/bash
source "common.sh"
$Multini --get "$InIni" 'Slashes/Test' './Dir1/File' > "$OutIni"
compare

View File

@ -1,10 +1,11 @@
#!/bin/bash #!/bin/bash
DEF='\e[0m'; BLD='\e[1m'; RED='\e[31m'; GRN='\e[32m'; WHT='\e[97m' DEF='\e[0m'; BLD='\e[1m'; RED='\e[31m'; GRN='\e[32m'; WHT='\e[97m'
ScriptFullname=$(readlink -e "$0") ScriptFullname=$(readlink -e "$0")
ScriptName=$(echo "$ScriptFullname" | awk -F '/' '{print $NF;}') ScriptName=$(echo "$ScriptFullname" | awk -F '/' '{print $NF;}')
ScriptDir=$(dirname "$ScriptFullname") ScriptDir=$(dirname "$ScriptFullname")
TestDir="$ScriptDir/tests" TestDir="$ScriptDir/data"
Multini=$(readlink -e "$1") Multini=$(readlink -e "$1")
if [[ -z "$Multini" ]]; then if [[ -z "$Multini" ]]; then