Giter Site home page Giter Site logo

jimmycushnie / succ Goto Github PK

View Code? Open in Web Editor NEW
155.0 8.0 16.0 3.35 MB

Sexy and Utilitarian Code Configuration

License: Do What The F*ck You Want To Public License

C# 100.00%
markup-language serialization config configuration-files csharp-library unity unity3d unity3d-plugin serialization-library serialization-format

succ's Introduction

Sexy and Utilitarian Code Configuration
Created by Jimmy Cushnie


Do your configuration files look like this?

<weapons>
    <weapon>
        <name>sword</name>
        <damage>10</damage>
        <attackSpeed>1</attackSpeed>
    </weapon>
    <weapon>
        <name>dagger</name>
        <damage>6</damage>
        <attackSpeed>1.3</attackSpeed>
    </weapon>
    <weapon>
        <name>axe</name>
        <damage>20</damage>
        <attackSpeed>0.4</attackSpeed>
    </weapon>
</weapons>

Do your configuration files, god forbid, look like this? cough cougheasy save

{"weapons":{"__type":"System.Collections.Generic.List`1[[Weapon, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]],mscorlib","value":[{"name":"sword","damage":10,"attackSpeed":1},{"name":"dagger","damage":6,"attackSpeed":1.3},{"name":"axe","damage":20,"attackSpeed":0.4}]}}

With SUCC, your configuration files can look like this:

weapons:
    -
        name: sword
        damage: 10
        attackSpeed: 1
    -
        name: dagger
        damage: 6
        attackSpeed: 1.3
    -
        name: axe
        damage: 20
        attackSpeed: 0.4

Look at that. That's a beautiful configuration file. There's zero wasted space on formatting. Everything is laid out clearly so that it's easy to find what you're looking for. The file is fast for a human to read and fast for a human to edit. If you were working on this game and needed to add a new weapon type, what would you rather the configuration file look like?

Furthermore, SUCC gives you a lot of freedom when writing or editing config files. You can play around with the colon position and the indentation level, you can add whitespace, you can add comments. The following file will, to SUCC, load exactly the same as the preceding one:

weapons:
    -
      # the sword is your starting weapon, very general purpose.
      name        : sword
      damage      : 10
      attackSpeed : 1
      
    -
      # daggers are useful against enemies with slow attack rates.
      name        : dagger
      damage      : 6
      attackSpeed : 1.3
      
    -
      # you use an axe when you need to get rid of a low-health
      # enemy as quickly as possible.
      name        : axe
      damage      : 20 # this is overpowered. TODO balance better
      attackSpeed : 0.4

Not only are SUCC files easy to work with in a text editor, they're easy to work with in your code too. Here is all the code required to recreate that configuration file:

using System.Collections.Generic;
using SUCC;

public class Weapon
{
    public string name;
    public float damage;
    public float attackSpeed;
}

static class Program
{
    static void Main()
    {
        List<Weapon> weapons = new List<Weapon>()
        {
            new Weapon()
            {
                name = "sword",
                damage = 10,
                attackSpeed = 1
            },
            new Weapon()
            {
                name = "dagger",
                damage = 6,
                attackSpeed = 1.3f
            },
            new Weapon()
            {
                name = "axe",
                damage = 20,
                attackSpeed = 0.4f
            },
        };

        var file = new DataFile("weaponsFile");
        file.Set("weapons", weapons);
    }
}

The important part of that is

var file = new DataFile("weaponsFile");
file.Set("weapons", weapons);

You keep a reference to that DataFile variable, and later when you need to read it, it's as simple as this:

var weaponsList = file.Get<List<Weapon>>("weapons");

But it can be even easier. You just do

var weaponsList = file.Get("weapons", defaultValue: weapons);

SUCC will check if a value called "weapons" exists in the file. If so, it will read the file and give you that data. If not, it will save defaultValue to the file and return it to you.

Start Using SUCC

Much more information about SUCC can be found on the wiki. If you're new to SUCC, you probably want to see the Installing and Getting Started pages.

Related Projects

In C#

InterSUCC is an extension for SUCC that lets you create SUCC DataFiles which implement an interface type. Getting and setting the properties of those interfaces gets and sets the values in the DataFiles.

SUCC in Other Languages

Check out SUCC4J by FalsePattern, a full port of SUCC to java!

There are also ongoing projects to port SUCC to Rust and node.js.

Also check out cSUCC, a tool for reading and writing values to SUCC files in C.

SUCC Utilities

Sublime SUCC by pipe01 provides syntax highlighting for SUCC files in Sublime Text 3.

succ's People

Contributors

brookemorgan avatar ecconia avatar forloveofcats avatar jimmycushnie avatar pipe01 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

succ's Issues

DefaultFileText doesn't work when the DataFile is created via field initializer

I am pretty sure this is a compiler bug. It happens in the standalone c# version, but it does not happen with the Unity version.

static class Test
{
    // this creates an empty file
    static DataFile file = new DataFile("test"), defaultFileText: "# this is a test");

    static void Main()
    {
        // this creates a file with the text "# this is a test"
        var file = new DataFile("test2", defaultFileText: "# this is a test");
    }
}

I have found through testing that the defaultFileText variable is being set to null before it reaches the constructor method.

Improve tests

SUCC's tests were the first tests I ever wrote, and unfortunately I only discovered this Unit Testing Best Practices page after I finished them. All the tests should be refactored to conform to the best practices, and be very specific about what failed when there is a failure.

Write data to disk on a separate thread

The main trouble is concurrency: if multiple "save file" commands are issued very quickly, they absolutely must be executed in the order they were called, lest outdated data be saved to disk

Try to preserve column of comment start

Suppose we have the following file:

key     : someValue                 # comment
key2    : shortValue                # another comment lmao

If we edit the value of key2 to be longer, the file will now look like this:

key     : someValue                 # comment
key2    : veryVeryLongValue                # another comment lmao

This is obviously not ideal. When the user creates pretty file formatting, SUCC should do its best to preserve that prettiness when the data changes.

SUCC should be smart enough to use constructors when deserializing

Suppose I have the following class:

public class Color
{
    public byte R, G, B;
    public Color(byte r, byte g, byte b) => (R, G, B) = (r, g, b);
}

Currently, SUCC cannot deserialize this type, because it requires complex types to have a parameterless constructor. The system should be upgraded to check the constructor parameter names against the member names, and use those instead. Related: #14

Tab support?

I was just weighing the pros and cons of INI or YAML for my upcoming game when I fell aware to SUCC.

I totally dig it!

Just one question; with all these variable options for indentation, how about tabs? Is it supported?

Ensure that there is a blank line following all content

As requested here is the issue to track this.

In the current LW beta all .succ files I have checked have content on the last line. While very minor is it generally good form to ensure at least one blank line at the end of a text file.

Do a big refactor of everything

The core of this project was written when I was a much less seasoned programmer, and SUCC as a whole is not up to my current standards of code quality. Todo, at some point: refactor the whole damn thing.

Allow multi-line strings to have a newline in the file without having a newline in the string

It is awkward to work with files which have very long strings without line breaks. There should be a way to break the line in the file without changing the returned string when it is loaded by SUCC.

One option is to have a character at the end of lines which tells the parser to ignore the line breaks.

Current:

Message: """
    What the fuck did you just fucking say about me, you little bitch? I'll have you know I graduated top of my class in the Navy Seals, and I've been involved in numerous secret raids on Al-Quaeda, and I have over 300 confirmed kills. I am trained in gorilla warfare and I'm the top sniper in the entire US armed forces. You are nothing to me but just another target. I will wipe you the fuck out with precision the likes of which has never been seen before on this Earth, mark my fucking words. You think you can get away with saying that shit to me over the Internet? Think again, fucker. As we speak I am contacting my secret network of spies across the USA and your IP is being traced right now so you better prepare for the storm, maggot. The storm that wipes out the pathetic little thing you call your life. You're fucking dead, kid. I can be anywhere, anytime, and I can kill you in over seven hundred ways, and that's just with my bare hands. Not only am I extensively trained in unarmed combat, but I have access to the entire arsenal of the United States Marine Corps and I will use it to its full extent to wipe your miserable ass off the face of the continent, you little shit. If only you could have known what unholy retribution your little "clever" comment was about to bring down upon you, maybe you would have held your fucking tongue. But you couldn't, you didn't, and now you're paying the price, you goddamn idiot. I will shit fury all over you and you will drown in it. You're fucking dead, kiddo.
    """

Desired:

Message: """
    What the fuck did you just fucking say about me, you little bitch? \
    I'll have you know I graduated top of my class in the Navy Seals, \
    and I've been involved in numerous secret raids on Al-Quaeda, and \
    I have over 300 confirmed kills. I am trained in gorilla warfare \
    and I'm the top sniper in the entire US armed forces. You are nothing \
    to me but just another target. I will wipe you the fuck out with \
    precision the likes of which has never been seen before on this Earth, \
    mark my fucking words. You think you can get away with saying that \
    shit to me over the Internet? Think again, fucker. As we speak I am \
    contacting my secret network of spies across the USA and your IP is \
    being traced right now so you better prepare for the storm, maggot. \
    The storm that wipes out the pathetic little thing you call your life. \
    You're fucking dead, kid. I can be anywhere, anytime, and I can kill \
    you in over seven hundred ways, and that's just with my bare hands. \
    Not only am I extensively trained in unarmed combat, but I have \
    access to the entire arsenal of the United States Marine Corps and \
    I will use it to its full extent to wipe your miserable ass off the \
    face of the continent, you little shit. If only you could have known \
    what unholy retribution your little "clever" comment was about to bring \
    down upon you, maybe you would have held your fucking tongue. But you \
    couldn't, you didn't, and now you're paying the price, you goddamn idiot. \
    I will shit fury all over you and you will drown in it. You're fucking \
    dead, kiddo.
    """

Collection shortcuts

It would be nice to have a compact way of writing collections. I.e.

collection:
    - 22
    - 10
    - 35
    - 0

shortcutCollection: [22, 10, 35, 0]

Careful consideration should be given to whatever syntax is chosen.

HashTag within one-line strings

When using SUCC I often stumble across the issue, that it has been a few months and I forgot that one has to escape # inside strings.

Knowledge background:

To my knowledge there are 3 types of strings:

  • One line: <key>: <value>
  • One line quoted: <key>: "<value>"
  • Block:
<key>: """
<value>
"""

All three can be at any point be stopped with # to start a comment. And \# will place a # into the content.

Problem:

I understand that comments can and should be possible/escapable in one-line string values and block-string values.

But they just make no sense in quoted one line string. As after a comment, there is no possible way for the closing " to be added. Hence it is basically destroying the value of the string.
One could argue, that the opening " would be part of the message - but then that should be escaped, else it would be misleading.

Suggestion:

If I am with my understanding correct, and the simple-quoted string is indeed limited to a single line.
Then my proposal is, to ignore # inside of such string (as it makes no sense).

Allow base types to be loaded when serialized as a complex type

Consider the following type.

struct Color
{
    public byte r;
    public byte g;
    public byte b;
}

If we save it as SUCC, it will look something like this:

color:
    r: 120
    g: 142
    b: 69

Now suppose later we make Color a base type, saving and loading it as a hex code:

color: 788e45

At this point, SUCC will be unable to load the first example, as base types must ALWAYS be saved and loaded as their single-line value.

Proposal: if SUCC tries to load a node as a base type, and that node has child nodes, SUCC should treat the base type as a complex type.

Add benchmarks

Performance is not a focus of this project, but of course it'll ideally be as fast as possible, and ideally we never introduce any regressions to performance. To keep track of performance and in particular to track changes to performance across changes to the code, I intend to add a SUCC.Benchmarks project. This project, a lovely companion to the existing SUCC.Tests, will contain stress-testy benchmarks for various aspects of the library, including serialization and deserialization of all the different types, parsing files, and saving files.

Way of treating multiple ReadOnlyDataFiles as one giant file

In Logic World, we're using SUCC for localization data. Since each language has a large number of localization keys, the data is split across multiple files for each language (i.e. English_UI.succ, English_components.succ ect).

Within our code, we're manually extracting the keys from each of these files and combining them into one giant dictionary. This functionality should be built-in to SUCC.

I think the ideal interface would be something like

new DistributedReadOnlyDataFile(params string[] path)

There should also be a constructor that takes an IReadOnlyList

support for multi-dimensional arrays

probably the best way to do this is by treating them as nested arrays. A 2d array is saved the same was as an array of arrays, a 3d array is saved the same way as an array of arrays of arrays, ect

Saving dictionaries can unintentionally generate invalid data files

void Test()
{
    var dicc = new Dictionary<int, Vector3>()
    {
        [22] = new Vector3(-12, 323, 432.43f),
        [55] = new Vector3(-1, 0, 100),
        [-100] = new Vector3(Mathf.PI, Mathf.PI, Mathf.PI),
    };

    var file = new DataFile("test", autoSave: true);
    file.Set("dicc boi", dicc);
}

That code generates this file:

dicc boi:
    22:
        x: -12
        y: 323
        z: 432.43
    55:
        x: -1
        y: 0
        z: 100
    -100:
        x: 3.141593
        y: 3.141593
        z: 3.141593

Notice the key called "-100". Keys are not allowed to begin with -, as that character is reserved for list nodes. Trying to read the file later will throw errors. This can also happen when using DataFile.SaveAsDictionary().

The solution is probably to allow - in key nodes, and determine what is a list node by the absence of :.

simplify multi-line strings

Current way:

MultiLineString: """
    here is line one
    here is line two
    """

There's really no need for the triple quotes. Desired:

MultiLineString:
    here is line one
    here is line two

Complications with this: the parser needs to use a more advanced method of detecting a multi-line string, so that it knows not to fail when those lines don't have a : in them.

Error when program is setting up wachter

the saving system is working when I am playing the game in the unity editor. But when I build my game and launch it, I get an error when it tries to make a data file. I think it is the wachter it tries to setup

line of code for making datafile: static DataFile Config = new DataFile("ProgramConfig");
error:

Uploading Crash Report
NotImplementedException: The method or operation is not implemented.
at System.IO.FileSystemWatcher..ctor (System.String path, System.String filter) [0x00006] in :0
at (wrapper remoting-invoke-with-check) System.IO.FileSystemWatcher..ctor(string,string)
at SUCC.DataFileBase.SetupWatcher () [0x0000d] in C:\Users\tfeij\Documents\Unity\The Kingdom\Assets\SUCC\SUCC\DataFiles\DataFileBase.cs:180
at SUCC.DataFileBase..ctor (System.String path, System.String defaultFile, System.Boolean autoReload) [0x000f8] in C:\Users\tfeij\Documents\Unity\The Kingdom\Assets\SUCC\SUCC\DataFiles\DataFileBase.cs:41
at SUCC.DataFile..ctor (System.String path, SUCC.FileStyle style, System.String defaultFile, System.Boolean autoSave, System.Boolean autoReload) [0x0000b] in C:\Users\tfeij\Documents\Unity\The Kingdom\Assets\SUCC\SUCC\DataFiles\DataFile.cs:39
at SUCC.DataFile..ctor (System.String path, System.String defaultFile, System.Boolean autoSave, System.Boolean autoReload) [0x00000] in C:\Users\tfeij\Documents\Unity\The Kingdom\Assets\SUCC\SUCC\DataFiles\DataFile.cs:29
at Game.DataSystem..cctor () [0x00000] in C:\Users\tfeij\Documents\Unity\The Kingdom\Assets\Scripts\SaveLoad\DataSystem.cs:8
Rethrow as TypeInitializationException: The type initializer for 'Game.DataSystem' threw an exception.
at Game.SavingSystem.Start () [0x00022] in C:\Users\tfeij\Documents\Unity\The Kingdom\Assets\Scripts\SaveLoad\SavingSystem.cs:19

Better constructor shortcuts

If a type has two constructors that take the same number of parameters, it chooses whichever comes first for use in constructor shortcuts.

class Example
{
    public Example(int i)
    {

    }
    public Example(string s)
    {

    }
}

if we try to use ("this is a string") as a shortcut for an Example, there will be an error as it will try to use the int shortcut. What should happen is that if there are multiple constructors with the same number of parameters, it keeps trying them until either there is no error or all constructors have been tried.

Better parsing errors

Parsing errors currently only tell you what kind of error happened. Sometimes they quote you the part of the file that caused the error. Every time a parsing error is thrown, the following information should be included:

  • the full path of the file
  • the line number on which the error occurred

Parsing errors should probably be their own kind of exception as well.

Better way of writing rational floats

when I'm writing configuration files, they're often filled with numbers like 0.3333333333 and 1.1666666666. It would be nice to be able to just write those as fractions, i.e. 1/3 and 7/6.

Serialize/deserialize flag enums in a nice way

[Flags]
enum Flags
{
    None = 0,
    UnionJack = 1,
    USA = 2,
    Communist = 4,
    SouthKorea = 8,
}

// ...

var file = new DataFile("example");

var communistBritain = Flags.UnionJack | Flags.Communist;
file.Set("flags", communistBritain);

example.succ will contain the following:

flags: 5

It would be nicer if it contained something like this:

flags: UnionJack | Communist

or perhaps

flags: UnionJack, Communist

or maybe even

flags: UnionJack and Communist

Or maybe SUCC should support all three syntaxes, and the one that's used is a FileStyle setting.

Improve ordering of members when saved

Currently the order members are listed in an apparently nondeterministic order, however in my experience it is almost always the derived class members and then the base class members, in the order the members are declared in the source file.

Order of saved members should be deterministic and reliable. The simplest way would be to do it alphabetically, but I would prefer to use the following rules. I am not sure if this is possible, but it's my ideal:

  • Members are listed in order of least to most derived class
  • Members within a single class are listed in the order of their listing in the source file

And perhaps we could have an attribute on members to customize their saving order.

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.