Giter Site home page Giter Site logo

theelectronwill / night-config Goto Github PK

View Code? Open in Web Editor NEW
211.0 10.0 27.0 1.9 MB

Powerful java configuration library for toml, yaml, hocon, json and in-memory configurations

License: GNU Lesser General Public License v3.0

Java 99.99% HTML 0.01%
java-library toml hocon json yaml java-8 configuration configuration-management minecraft-forge java-9

night-config's Introduction

Night Config

Maven Central javadoc CircleCI

Introduction

NightConfig is a powerful yet easy-to-use java configuration library, written in Java 8.

It supports the following formats:

How to use

  • Please read the extensive wiki.
  • You can also try the runnable examples (see below).

Glimpse

// Simple builder:
FileConfig conf = FileConfig.of("the/file/config.toml");

// Advanced builder, default resource, autosave and much more (-> cf the wiki)
CommentedFileConfig config = CommentedFileConfig.builder("myConfig.toml").defaultResource("defaultConfig.toml").autosave().build();
config.load(); // This actually reads the config

String name = config.get("username"); // Generic return type!
List<String> names = config.get("users_list"); // Generic return type!
long id = config.getLong("account.id"); // Compound path: key "id" in subconfig "account"
int points = config.getIntOrElse("account.score", defaultScore); // Default value

config.set("account.score", points*2);

String comment = config.getComment("user");
// NightConfig saves the config's comments (for TOML and HOCON)

// config.save(); not needed here thanks to autosave()
config.close(); // Close the FileConfig once you're done with it :)

Running the examples

Each file in examples/src/main/java has a main function and shows how to use NightConfig for many different use cases.

To run an example:

  1. Clone this repository.
  2. cd to it
  3. Run ./gradlew examples:run -PmainClass=${CLASS} by replacing ${CLASS} with the example of your choice.

For example, to run FileConfigExample.java:

./gradlew examples:run -PmainClass=FileConfigExample

The file be compiled automatically, and the given main class will be executed.

Project building

NightConfig is built with Gradle. The project is divided in several modules, the "core" module plus one module per supported configuration format. Please read the wiki for more information.

The releases are available on Maven Central and JitPack.

Old Android modules

Older versions of Android (before Android Oreo) didn't provide the packages java.util.function and java.nio.file, which NightConfig heavily uses. To attempt to mitigate these issues, I made a special version of each modules, suffixed with _android, that you could use instead of the regular modules.

These old _android modules are deprecated and will no longer receive updates. The maintainance burden of these modules is not worth it, and these versions of Android have reached end of life since several years already.

night-config's People

Contributors

0x3c50 avatar cadiboo avatar mnlipp avatar paintninja avatar stein-n avatar technicianlp avatar theelectronwill avatar tterrag1098 avatar vaperion avatar vectrixdevelops avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

night-config's Issues

Commented File Config autosave doesn't automatically save

configData = CommentedFileConfig.builder(configFile).autosave().autoreload().build();

This code won't generate a config that is autosaving. It looks the resultant config object doesn't delegate to the right config to accomplish autosave - it's calling through to the normal config, not the autosaving one (there seems to be two?).

            configData.add("newsetting", "fish");
            configData.setComment("newsetting", "Super secret new setting");

Doesn't result in the config file being written with the new value or the new comment for said value.

Write a wiki for version 1.x

The wiki should explain:

  • How the library is organized around the Config interface.
  • How to use concrete Config instances.
  • How to read/write configurations.
  • How to use a ConfigSpec to auto-correct configurations and detect errors.
  • How to serialize objects to configs and vice-versa.

clearComments does't actually clear comments

As stated, AbstractCommentedConfig.clearComments() doesn't actually clear the comments. It clears the comment map, but the entry set still contains its comments, and that is what is referenced when writing the file, so the comments remain.

Extra empty comments

After parsing, every assignment line has an has an empty comment for that line, even when there is no comment on the line. Shouldn't the comment be null if there is no comment?

Write a wiki for version 3

Night-Config has been stable for a while, and it would be good to have a proper wiki for the last version, ie version 3. I'll write it soonish.

Improve the CheckedConfig

  • Better checking of setValue(path, value) : do a recursive check if the value is a Config
  • Apply checks on the Map returned by asMap() too.

Autosave issue is back? (from v3.2.0)

The following code doesn't work from v3.2.0.
If I switch to v3.1.0 it works.

public class ConfigAdapter {

    private File configFile;
    private FileConfig config;

    /**
     * @param configFile File from which read previous preference
     *                    and on which write updated preference
     */
    public ConfigAdapter(@NotNull File configFile) {
        Log.debug("constr:: config file: " + configFile.getAbsolutePath());

        this.configFile = configFile;
        this.config = FileConfig.builder(configFile,JsonFormat.fancyInstance())
                .sync()
                .autosave()
                .autoreload()
                .build();

        ConversionTable conversionTable = new ConversionTable();
        conversionTable.put(Long.class, Long::intValue);
        config = conversionTable.wrapRead(config);
        Log.debug("constr:: build conversion table");

        config.load();
        Log.debug("constr:: config.load()");
    }

    /**
     * Find and return value at searched key, or default.
     *
     * @param k   The key to search
     * @param def The default value if object not found
     * @param <T> The value's type
     * @return The value at {@code k} or {@code def}
     */
    public <T> T get(String k, T def) {
        Log.debug("get:: (" + k + ", " + def + ")");

        T x = config.get(k);
        return x != null ? x : def;
    }

    /**
     * Replaces old value with new one, return old.
     *
     * @param k     The value's key
     * @param v     The value to set
     * @param <T>   The type of old value
     * @return      The old value if any, or null
     */
    public <T> T put(String k, T v) {
        Log.debug("put:: (" + k + ", " + v + ")");

        T x = config.set(k,v);
        return x;
    }

}

Tell me if you need some specific information or if I'm doing something wrong.
Thanks!

Provides (optionally) thread-safe configurations

Having a thread-safe configuration would be practical for some projects (for instance https://github.com/mcphoton/Photon-Server). But it would also be useless for some others, therefore it should be up to the user of the library to choose if the configs they create are thread-safe or not.

I've finished to work on this feature, and it will be part of v3.0 stable, which is to be released very soon.

triple quotes issue

str1 = """
Roses are red
Violets are blue"""

this toml example does not parse

TomlParser fails to parse the examples of the specification

str5 = """
The quick brown \


  fox jumps over \
    the lazy dog."""

str6 = """\
       The quick brown \
       fox jumps over \
       the lazy dog.\
       """

data = [ ["gamma", "delta"], [1, 2] ]

arr3 = [ [ 1, 2 ], [3, 4, 5] ]

int5 = 1_000
int6 = 5_349_221
int7 = 1_2_3_4_5     # VALID but discouraged

flt8 = 9_224_617.445_991_228_313

[ d.e.f ]          # same as [d.e.f]
[ g .  h  . i ]    # same as [g.h.i]
[ j . "สž" . 'l' ]  # same as [j."สž".'l']



[[fruit]]
  name = "apple"

  [fruit.physical]
    color = "red"
    shape = "round"

  [[fruit.variety]]
    name = "red delicious"

  [[fruit.variety]]
    name = "granny smith"

[[fruit]]
  name = "banana"

  [[fruit.variety]]
    name = "plantain"

according to current toml readme this should also work, but it does not

Write a wiki for version 2.x

  • What are the differences between version 1 and version 2.
    --> This is described in the release notes. Put a link in the wiki.
  • The UnmodifiableConfig, Config and CommentedConfig interfaces.
  • The concrete Config instances.
  • How to read/write configurations.
  • ConfigSpec
  • ObjectConverter
  • ObjectBinder
  • Annotations: Path, AdvancedPath, Spec..., Conversion, ForceBreakdown

Concurrent config doesn't support null values

Thread-safe configurations based on ConcurrentHashMap doesn't accept null values because of a limitation of ConcurrentHashMap. This is a problem when using JSON because null values are valid and should be supported.

A solution is to replace null values by a special singleton object representing the concept of null.

TomlParser fails when there are underscores inside numbers

(reported by guai in issue 12)
Parsing this data:

int5 = 1_000

Produces:

com.electronwill.nightconfig.core.io.ParsingException: Invalid value: 1_000
	at com.electronwill.nightconfig.core.io.Utils.parseLong(Utils.java:69)
	at com.electronwill.nightconfig.toml.ValueParser.parseNumber(ValueParser.java:77)
	at com.electronwill.nightconfig.toml.ValueParser.parseNumberOrDateTime(ValueParser.java:65)
	at com.electronwill.nightconfig.toml.ValueParser.parse(ValueParser.java:52)
	at com.electronwill.nightconfig.toml.ValueParser.parse(ValueParser.java:57)
	at com.electronwill.nightconfig.toml.TableParser.parseNormal(TableParser.java:55)
	at com.electronwill.nightconfig.toml.TomlParser.parse(TomlParser.java:36)
	at com.electronwill.nightconfig.toml.TomlParser.parse(TomlParser.java:27)
	at com.electronwill.nightconfig.toml.TomlParser.parse(TomlParser.java:19)
	at com.electronwill.nightconfig.core.io.ConfigParser.parse(ConfigParser.java:78)

ParsingException when the last line is a comment

ver 2.1

Exception in thread "main" com.electronwill.nightconfig.core.io.ParsingException: Not enough data available
	at com.electronwill.nightconfig.core.io.ParsingException.notEnoughData(ParsingException.java:22)
	at com.electronwill.nightconfig.core.io.ReaderInput.directReadChar(ReaderInput.java:36)
	at com.electronwill.nightconfig.core.io.AbstractInput.readChar(AbstractInput.java:49)
	at com.electronwill.nightconfig.core.io.AbstractInput.readCharsUntil(AbstractInput.java:123)
	at com.electronwill.nightconfig.toml.Toml.readLine(Toml.java:63)
	at com.electronwill.nightconfig.toml.Toml.readUseful(Toml.java:36)
	at com.electronwill.nightconfig.toml.TableParser.parseNormal(TableParser.java:51)
	at com.electronwill.nightconfig.toml.TableParser.parseNormal(TableParser.java:99)
	at com.electronwill.nightconfig.toml.TomlParser.parse(TomlParser.java:76)
	at com.electronwill.nightconfig.toml.TomlParser.parse(TomlParser.java:31)
	at com.electronwill.nightconfig.toml.TomlParser.parse(TomlParser.java:23)
	at com.electronwill.nightconfig.core.io.ConfigParser.parse(ConfigParser.java:103)

being thrown when the toml file contains this two lines at the very end:

#[geometry]
#	disabled = false

with no newline after them
In case when there is a newline - it's ok.

Suggestion - Make #get() return primitives to avoid ambiguity between Integer and Long.

When a field is a number, Config#get returns an Integer or a Long and not the primitive types.
So if I have a field that can have any value between 0 and 2^63, sometimes Config#get will return an Integer and sometimes a Long. The problem is that an Integer cannot be casted to a Long.

The workaround that i've found looks like this: long value = ((Number) config.get("path")).longValue(); but it's pretty ugly and intelliJ see it as a redundant cast (but it's not).

But if Config#get can return a primitive, it will be automatically casted to a long and everything will be fine.
Not tested but the same problem can proably occur with byte and short.

Common interface for config writers and parsers

Something like this:

interface ConfigWriter {
    void writeConfig(Config config, CharacterOutput output);
}

interface ConfigParser<T extends Config> {
    T parseConfig(CharacterInput input);
}
  • ConfigWriter
  • ConfigParser

Publish to maven central

Iโ€™ll try to add NightConfig to mavencentral so that you can use it more easily in your projects.

NoSuchMethodError: No virtual method toPath()

Hello!
I have a very big problem.

I've tried to debug my Android application and I discovered that under Android 8, the method used to add the file watcher does not work. In particular the file.toPath() does not exist.

Here is the stack trace:

09-24 10:16:52.647 18557-18557/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: it.bcv.invadelite.apptest, PID: 18557
    java.lang.NoSuchMethodError: No virtual method toPath()Ljava/nio/file/Path; in class Ljava/io/File; or its super classes (declaration of 'java.io.File' appears in /system/framework/core-oj.jar)
        at com.electronwill.nightconfig.core.file.FileWatcher.addWatch(FileWatcher.java:69)
        at com.electronwill.nightconfig.core.file.AutoreloadFileConfig.<init>(AutoreloadFileConfig.java:17)
        at com.electronwill.nightconfig.core.file.FileConfigBuilder.build(FileConfigBuilder.java:193)
        at it.bcv.invade.appdb.ConfigAdapter.<init>(ConfigAdapter.java:37)
        at it.bcv.invade.appdb.Db.<init>(Db.java:51)
        at it.bcv.invade.appdb.Db.init(Db.java:75)
        at it.bcv.invadelite.activities.StartActivity.initDatabase(StartActivity.java:161)
        at it.bcv.invadelite.activities.StartActivity.onCreate(StartActivity.java:123)

The file watcher method has the following implementation:

public void addWatch(File file, Runnable changeHandler) throws IOException {
	addWatch(file.toPath(), changeHandler);
}

and the toPath gives me an error.

Can you change this in order to get the backward compatibility?

Thanks!

Keep track of the positions of comments

In TOML, when you parse the following

# I'm just messing around with it
title = "TOML Example" # This comment comes at the end of the line

It doesn't keep track of where the comments came from, so rendering it back out results in

# I'm just messing around with it
# This comment comes at the end of the line
title = "TOML Example"

It would be cool if it could keep track of where the comment came from and render it accordingly.

Tested with 3.0.1

More units tests!

  • JsonParser
  • JsonWriter
  • TomlParser
  • TomlWriter
  • HoconWriter
  • SimpleConfig
  • ConfigSpec
  • ConfigToObjectMapper
  • ObjectToConfigMapper
  • IntDeque

Array parsing fails with numbers and booleans if there is no trailing comma

(reported by guai in issue 12)
For instance:

with_trailing = [true, false, true,] # Works fine
without_trailing = [true, false, true] # Error!
string_array = ["a", 'b'] # Works fine

throws this error:

com.electronwill.nightconfig.core.io.ParsingException: Invalid value: 2]
	at com.electronwill.nightconfig.core.io.Utils.parseLong(Utils.java:69)
	at com.electronwill.nightconfig.toml.ValueParser.parseNumber(ValueParser.java:77)
	at com.electronwill.nightconfig.toml.ValueParser.parseNumberOrDateTime(ValueParser.java:65)
	at com.electronwill.nightconfig.toml.ValueParser.parse(ValueParser.java:52)
	at com.electronwill.nightconfig.toml.ArrayParser.parse(ArrayParser.java:23)
	at com.electronwill.nightconfig.toml.ValueParser.parse(ValueParser.java:29)
	at com.electronwill.nightconfig.toml.ArrayParser.parse(ArrayParser.java:23)
	at com.electronwill.nightconfig.toml.ValueParser.parse(ValueParser.java:29)
	at com.electronwill.nightconfig.toml.ValueParser.parse(ValueParser.java:57)
	at com.electronwill.nightconfig.toml.TableParser.parseNormal(TableParser.java:55)
	at com.electronwill.nightconfig.toml.TomlParser.parse(TomlParser.java:36)
	at com.electronwill.nightconfig.toml.TomlParser.parse(TomlParser.java:27)
	at com.electronwill.nightconfig.toml.TomlParser.parse(TomlParser.java:19)
	at com.electronwill.nightconfig.core.io.ConfigParser.parse(ConfigParser.java:78)

Incorrect type when using ObjectConverter on array of tables

I believe I've found a bug in how the ObjectConverter handles an array of tables. To reproduce:

1. Create: /path/to/file.toml

[[b.cees]]
someString = "test1"
someInt = 123
[[b.cees]]
someString = "test2"
someInt = 456

2. Create MWE.java

import com.electronwill.nightconfig.core.conversion.ObjectConverter;
import com.electronwill.nightconfig.core.file.FileConfig;

import java.util.List;

public class MWE {
    public static class A {
        B b;

        public A() { }
    }

    public static class B {
        List<C> cees;

        public B() { }
    }

    public static class C {
        String someString;
        int someInt;

        public C() { }
    }

    public static void main(String[] args) {
        FileConfig tomlFile = FileConfig.of("/path/to/file.toml").checked();

        tomlFile.load();

        A a = new ObjectConverter().toObject(tomlFile, A::new);

        System.out.println(a.b.cees.get(1).someString);
    }
}

3. Run MWE.java

Expected output: test2
Actual output:

Exception in thread "main" java.lang.ClassCastException: com.electronwill.nightconfig.core.SimpleCommentedConfig cannot be cast to MWE$C
	at MWE.main(MWE.java:33)

Line ending backslash doesn't work correctly

(reported by guai in issue 12)
From the TOML spec:

# The following strings are byte-for-byte equivalent:
str1 = "The quick brown fox jumps over the lazy dog."

str2 = """
The quick brown \


  fox jumps over \
    the lazy dog."""

str3 = """\
       The quick brown \
       fox jumps over \
       the lazy dog.\
       """

Because

When the last non-whitespace character on a line is a , it will be trimmed along with all whitespace (including newlines) up to the next non-whitespace character or closing delimiter.

But it produces this error

com.electronwill.nightconfig.core.io.ParsingException: Invalid escapement: \
	at com.electronwill.nightconfig.toml.StringParser.escape(StringParser.java:135)
	at com.electronwill.nightconfig.toml.StringParser.parseMultiBasic(StringParser.java:70)
	at com.electronwill.nightconfig.toml.ValueParser.parse(ValueParser.java:39)
	at com.electronwill.nightconfig.toml.ValueParser.parse(ValueParser.java:57)
	at com.electronwill.nightconfig.toml.TableParser.parseNormal(TableParser.java:55)
	at com.electronwill.nightconfig.toml.TomlParser.parse(TomlParser.java:36)
	at com.electronwill.nightconfig.toml.TomlParser.parse(TomlParser.java:27)
	at com.electronwill.nightconfig.toml.TomlParser.parse(TomlParser.java:19)
	at com.electronwill.nightconfig.core.io.ConfigParser.parse(ConfigParser.java:78)

ConfigSpec.correct() does not correct fields with missing parents

Simple replication (apologies for the Kotlin, that is where I discovered it):

val spec = ConfigSpec()
spec.define("a.b", "")
val config = FileConfig.of("test.toml")
spec.correct(config)
val field: String = config.get("a.b")

I expect field to be set to 0; instead, the parent category ("a") is created but empty. A second call to spec.correct() does set "a.b", and a loop can correct fields with arbitrary nest depth:

while (!spec.isCorrect(config)) {
   spec.correct(config)
}

Because there is a convenient workaround I do not think this is high priority, but from the documentation of ConfigSpec this behavior was surprising.

Shortcut for getOptional().orElse

Transform this:

String a = config.getOptional("key").orElse("default value");
String b = config.getOptional("key").orElseGet(k -> myFunction(k));

into this:

String a = config.getOrElse("key", "default value");
String b = config.getOrElse("key", k -> myFunction(k));

Add an easy way to save the comments when converting to an object

Problem found when trying to use NightConfig for the Photon server's configuration: there is no simple way to copy all the comments (deeply) of a commented configuration. This would be very useful when converting config to object, because the conversion loses the comments.
Solution in that situation:

  1. Load the commented configuration
  2. Exports all its comments, including the comments of the sub-configs // needs improvement here
  3. Converts it to a custom object
  4. Converts the object to a config
  5. Adds the previously saved comments to this config // needs improvement here
  6. Save the config

JsonParser fails to parse empty object

Config file: {}
Error:

Exception in thread "main" com.electronwill.nightconfig.core.io.ParsingException: Invalid beginning of a key: }
    at com.electronwill.nightconfig.json.JsonParser.parseObject(JsonParser.java:111)
    at com.electronwill.nightconfig.json.JsonParser.parse(JsonParser.java:77)
    at com.electronwill.nightconfig.core.io.ConfigParser.parse(ConfigParser.java:141)
    at com.electronwill.nightconfig.core.io.ConfigParser.parse(ConfigParser.java:157)
    at com.electronwill.nightconfig.core.file.WriteAsyncFileConfig.load(WriteAsyncFileConfig.java:132)
    at Main.main(Main.java:23)

TomlParser doesn't handle nested array of tables

(reported by guai in issue 12)
This toml example throws an error:

[[fruit]]
  name = "apple"

  [fruit.physical]
    color = "red"
    shape = "round"

  [[fruit.variety]]
    name = "red delicious"

  [[fruit.variety]]
    name = "granny smith"

[[fruit]]
  name = "banana"

  [[fruit.variety]]
    name = "plantain"
java.lang.IllegalArgumentException: Cannot add an element to an intermediary value of type: class java.util.ArrayList
	at com.electronwill.nightconfig.core.MapConfig.setValue(MapConfig.java:60)
	at com.electronwill.nightconfig.toml.TomlParser.parse(TomlParser.java:77)
	at com.electronwill.nightconfig.toml.TomlParser.parse(TomlParser.java:27)
	at com.electronwill.nightconfig.toml.TomlParser.parse(TomlParser.java:19)
	at com.electronwill.nightconfig.core.io.ConfigParser.parse(ConfigParser.java:78)

Unexpected ParsingException when using autoreload + autosave

Hello,

I'm me, again.

I've encountered this following problem while executing sequential write (seconds of delay)...

  • i have defined:
config = FileConfig.builder(configFile,JsonFormat.fancyInstance())
                .sync()
                .autosave()
                .autoreload()
                .build();

public <T> T get(String k, T def) {
    Log.debug("get");
    T x = config.get(k);
    return x != null ? x : def;
}

public <T> T put(String k, T v) {
    Log.debug("put");
    return config.set(k,v);
}
  • i was doing some test and the problem was:
*** MAIN ***
// option 4 perform a read to a key
// option 5 write a random number on the same key

[ 4: read conf test, 5: write conf test ] ? chose: 4
[main] DEBUG it.bcv.invade.appdb.Configuration - get
97

[ 4: read conf test, 5: write conf test ] ? chose: 5
[main] DEBUG it.bcv.invade.appdb.Configuration - put

[ 4: read conf test, 5: write conf test ] ? chose: 5
[main] DEBUG it.bcv.invade.appdb.Configuration - put

[ 4: read conf test, 5: write conf test ] ? chose: 5
[main] DEBUG it.bcv.invade.appdb.Configuration - put

[ 4: read conf test, 5: write conf test ] ? chose: 5
[main] DEBUG it.bcv.invade.appdb.Configuration - put

[ 4: read conf test, 5: write conf test ] ? chose: 5
[main] DEBUG it.bcv.invade.appdb.Configuration - put

[ 4: read conf test, 5: write conf test ] ? chose: 5
[main] DEBUG it.bcv.invade.appdb.Configuration - put
Exception in thread "Thread-0" com.electronwill.nightconfig.core.io.ParsingException: Not enough data available
	at com.electronwill.nightconfig.core.io.ParsingException.notEnoughData(ParsingException.java:22)
	at com.electronwill.nightconfig.core.io.ReaderInput.directReadChar(ReaderInput.java:36)
	at com.electronwill.nightconfig.core.io.AbstractInput.readChar(AbstractInput.java:49)
	at com.electronwill.nightconfig.core.io.CharacterInput.readCharAndSkip(CharacterInput.java:59)
	at com.electronwill.nightconfig.json.JsonParser.parse(JsonParser.java:78)
	at com.electronwill.nightconfig.core.io.ConfigParser.parse(ConfigParser.java:149)
	at com.electronwill.nightconfig.core.io.ConfigParser.parse(ConfigParser.java:165)
	at com.electronwill.nightconfig.core.file.WriteSyncFileConfig.load(WriteSyncFileConfig.java:58)
	at com.electronwill.nightconfig.core.file.FileWatcher$WatcherThread.run(FileWatcher.java:174)

[ 4: read conf test, 5: write conf test ] ? chose: 

what is this exception? And why thrown only after a few writes? Should I catch it or i'm doing something wrong?

Thanks in advance!

ArrayIndexOutOfBoundsException while parsing toml file

Hi
this error appears in 3.0.3 and it was ok in 2.1.2
Test toml file can be found here https://github.com/guai/toml-test

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
	at com.electronwill.nightconfig.core.io.CharsWrapper.get(CharsWrapper.java:122)
	at com.electronwill.nightconfig.toml.Toml.readLine(Toml.java:65)
	at com.electronwill.nightconfig.toml.Toml.readUseful(Toml.java:36)
	at com.electronwill.nightconfig.toml.TableParser.parseNormal(TableParser.java:50)
	at com.electronwill.nightconfig.toml.TableParser.parseNormal(TableParser.java:103)
	at com.electronwill.nightconfig.toml.TomlParser.parse(TomlParser.java:96)
	at com.electronwill.nightconfig.toml.TomlParser.parse(TomlParser.java:37)
	at TomlTest.main(TomlTest.java:8)

Improve the ConfigSpecification

  • Accept List<String> instead of String only
  • Store the values' specifications differently, e.g in a Config instead of a Map<String, ValueSpec>

Support comments

It would be nice to support reading and writing comments.

  • UnmodifiableCommentedConfig
    • String getComment(path)
  • CommentedConfig
    • void setComment(path, comment)

Status:

  • HOCON
  • TOML
  • YAML (not possible because of snakeYaml)

NoFormatFoundException on every file

Hi,

i was using this library for some simple configuration handle, but i'm stucked with this problem:

this code

FileConfig config = FileConfig.of("config.json");
// FileConfig config = FileConfig.of("config.toml"); // like above
// FileConfig config = FileConfig.builder("config.json").build(); // has the same behaviour

always throws this exception

Exception in thread "main" com.electronwill.nightconfig.core.file.NoFormatFoundException: No suitable format for config.json
	at com.electronwill.nightconfig.core.file.FileConfig.of(FileConfig.java:66)
	at com.electronwill.nightconfig.core.file.FileConfig.of(FileConfig.java:92)
	at it.bcv.invade.appdb.Main.cfgTest(Main.java:83)
	at it.bcv.invade.appdb.Main.doMain(Main.java:33)
	at it.bcv.invade.appdb.Main.main(Main.java:25)

for every file and/or extension given.
I've tried to copy some json/toml examples from github, however i got this error.

What i'm doing wrong?

Thanks in advance!

Toml comments are not saved inside arrays

I found one more place where comments are not being kept, but I'm honestly not sure where they would be kept. The following

hosts = [
  "alpha", # Where does this comment go?
  "omega"
]

loses its comment and becomes

hosts = ["alpha", "omega"]

Tested in 3.0.1

(Sorry for all the issues, but I really do like your library)

FileConfig should not create an empty file for JSON

CREATE_EMPTY should actually write an empty json object {}, because an empty file isn't valid in json.

Exception in thread "main" com.electronwill.nightconfig.core.io.ParsingException: Not enough data available
    at com.electronwill.nightconfig.core.io.ParsingException.notEnoughData(ParsingException.java:22)
    at com.electronwill.nightconfig.core.io.ReaderInput.directReadChar(ReaderInput.java:36)
    at com.electronwill.nightconfig.core.io.AbstractInput.readChar(AbstractInput.java:49)
    at com.electronwill.nightconfig.core.io.CharacterInput.readCharAndSkip(CharacterInput.java:59)
    at com.electronwill.nightconfig.json.JsonParser.parse(JsonParser.java:72)
    at com.electronwill.nightconfig.core.io.ConfigParser.parse(ConfigParser.java:141)
    at com.electronwill.nightconfig.core.io.ConfigParser.parse(ConfigParser.java:157)
    at com.electronwill.nightconfig.core.file.WriteAsyncFileConfig.load(WriteAsyncFileConfig.java:132)
    at Main.main(Main.java:23)

Improve the README

The README should contain:

  • a short presentation of the library
  • how it is divided in different projects (core + 1/config language)
  • some examples
  • instructions on how to use it (with gradle, etc.).

Simplify the Config interface

Currently there are two getters and two writers per supported value type, plus general methods like getValue which returns an Object. It makes the Config interface bloated and should be simplified.
A better way would be to have these methods only:

<T> T getValue(path);
void setValue(path, Object);

The generic getValue method makes explicit cast unnecessary:

String str = config.getValue(stringPath);
List<Integer> list = config.getValue(intListPath);

Note that I would use "getValue" and not just "get" because I plan to add "getComment" later.

Toml comments are not saved with table arrays

One more (less important) bug with comments in TOML

If you add comments to table arrays, only the last one is kept. Here's an example to better explain

[[products]] # Table List 1
name = "Hammer" # Name 1
sku = 738594937

[[products]] # Table List 2
name = "Nail" # Name 2
sku = 284758393
color = "gray"

becomes

# Table List 2
[[products]]
	# Name 1
	name = "Hammer"
	sku = 738594937

[[products]]
	color = "gray"
	# Name 2
	name = "Nail"
	sku = 284758393

Notice the first table in the array is now marked as Table List 2 and the second is not marked.

Tested in 3.0.1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.