📜 ⬆️ ⬇️

thindf - new text data format (alternative to JSON)

File AppData \ Local \ Dropbox \ info.json:
{ "personal": { "host": 5060852864, "is_team": false, "subscription_type": "Basic", "path": "C:\\Users\\DNS\\Dropbox" } } 
In the new format looks like this:
 personal host = 5060852864 is_team = 0B subscription_type = Basic path = C:\Users\DNS\Dropbox 
Sublime Text Editor Configuration File:
 { "added_words": [ "plugin", "habrahabr", "" ], "default_line_ending": "unix", //"font_face": "Fira Code", "font_size": 11, "ignored_packages": [ "Sublimerge Pro", "Vintage" ], "ignored_words": [ "utf" ], "line_numbers": false, "show_encoding": true, "show_line_endings": true, "tab_size": 4, "theme": "Default.sublime-theme" } 
In the new format looks like this:
 added_words = [ plugin habrahabr  ] default_line_ending = unix //font_face = Fira Code font_size = 11 ignored_packages = [ Sublimerge Pro Vintage ] ignored_words = [ utf ] line_numbers = 0B show_encoding = 1B show_line_endings = 1B tab_size = 4 theme = Default.sublime-theme 

A bit of history


This format is due to its appearance in another format with the strange name blockpar.
Blockpar was developed by Alexey Dubovoy (one of the founders of Elemental Games) while working on the game Space Rangers. Subsequently, Alexander Zeberg (the former leading programmer of Katauri Interactive [ after the company's "disintegration" at Katauri Interactive and Elemental Games he went to Katauri ] ) decided to use this format for the game King's Bounty: Legend of the Knight.

The definition of each game object was stored in blockpar format in a separate file with the .atom extension, for example, here is a clipping from the data / data.kfs / spider.atom file :
 main { class=chesspiece model=spider.bma cullcat=0 } arena_params { race=neutral cost=24 level=1 leadership=14 attack=4 defense=4 ... resistances { physical=20 poison=0 magic=0 fire=-10 } ... } ... 

Subsequently [ while working on the Royal Quest project ] I slightly expanded this format so that instead of:
 button { name=close pos=400,600 size=200,40 image=button_close.png anchors=0,0,100,0 } 
write like this:
 button=close,400,600,200,40 { image=button_close.png anchors=0,0,100,0 } 

I also added support for multi-line string values ​​via the reverse apostrophe (backtick - `):
 button=... { onmouseover=` ... ` } 
Why I refused to `strings enclosed in reverse apostrophes`
In the value of the parameters, it is permissible to directly insert the script code, and in the comments in the code I use backward apostrophes in the same meaning as they are used in Markdown and PC markup . For example:
 if len(indentation_levels) and indentation_levels[-1][0] == -1: #    `{`    ,       `}` 

And finally, as a result of my acquaintance with Python, the idea of ​​abandoning curly braces so captured me that I decided that the blockpar format could be further simplified [by abandoning the mandatory curly braces ] .

Also influenced me:

Why 0B and 1B?
  • Often true / false is used for yes / no (YES / NO is used in Objective-C) , on / off, or enable / disable (for example: you can enable show line endings; turn logging on / off ; is digit? Yes ), and in Boolean algebra, 0 and 1 are used, so the use of the keywords true and false is in most cases quite controversial.
  • I do not like the truth / lie in the Russian version of the format, and 0V and 1B (here B is the Russian title c) can be associated with 0 Disabled and 1 Enabled. [The question of the expediency of the Russian version, please do not raise ]
  • 0B and 1B are used in the 11l programming language for the reasons indicated in the documentation .

Strings in single pair quotes


Another [ in addition to 0B and 1B ] controversial / unusual element of this format is the use of double quotes for raw strings [ without escape sequences \ escape sequences ] .
But my choice justifies the fact that the Unicode Consortium approved this year - the opening single pair quote code .
')
How such quotes typed on the keyboard - see here .

If the string contains unmatched quotes, then you need to "balance the string" in the same way as it is done in the PC markup to insert HTML-code.
For example, there is the string don't .
Since there is an unbalanced closing quote in it, add a balancing opening quote to the very beginning of the line: ' don't .
Balanced string is enclosed in double quotes: ' 'don't ' .
Now you need to somehow show the parser that the quotation mark added to the left should not be included in the string, since it is needed only to restore the balance . To do this, use the typewritten apostrophe character, which needs to be put one per each balancing quotation [ thus, one typewritten apostrophe "eats" one double quotation mark ] , in this case it must be placed at the beginning of the line: .
A balanced string can be inserted as it is into other strings in double quotes:
'text = '''don't'' .

Using


At the moment there is an implementation in Python and in JavaScript (you can try to convert JSON to a new format directly in the browser on the project’s web page ).

For Python, install as usual:
 pip install thindf 

For javascript:
 npm install thindf node const thindf = require('thindf'); 

And we use:

In conclusion, I will give a few more examples:
Some lines from my Default (Windows) .sublime-keymap :
 [ { "keys": ["f4"], "command": "f4" }, { "keys": ["shift+f4"], "command": "f4", "args": {"shift_key_pressed": true} }, { "keys": ["alt+shift+`"], "command": "insert", "args": {"characters": "`"} }, // ( { "keys": [":", ")"], "command": "insert_snippet", "args": {"contents": ":)(:"} }, { "keys": ["alt+9"], "context": [{"key": "selector", "operator": "equal", "operand": "text.pq"}], "command": "insert_pq" }, // ' (for balance) { "keys": ["alt+0"], "context": [{"key": "selector", "operator": "equal", "operand": "text.pq"}], "command": "insert", "args": {"characters": "'"} }, ] 
Using the new format, I would write this:
 f4 = on_f4() shift+f4 = on_f4(shift_key_pressed' 1B) alt+shift+` = insert(characters' '`') // ( :,) = insert_snippet(contents' ':)(:') alt+9 = if selector == 'text.pq' {insert_pq()} else 0B // ' (for balance) alt+0 = if selector == 'text.pq' {insert(characters' "'")} else 0B 

Slice from d.json file [ from plugin manager repository for Sublime Text ] :
 { "schema_version": "3.0.0", "packages": [ { "name": "Django Lookup Snippets", "details": "https://github.com/icycandle/sublime-django-lookup", "releases": [ { "sublime_text": "*", "tags": true } ] }, { "name": "Django Manage Commands", "details": "https://github.com/vladimirnani/DjangoCommands", "labels": ["Django", "python", "web", "management"], "releases": [ { "sublime_text": "<3000", "tags": "st2-" }, { "sublime_text": ">=3000", "tags": "st3-" } ] } ] } 
In the new format looks like this:
 schema_version = '3.0.0' packages = [ . name = Django Lookup Snippets details = https://github.com/icycandle/sublime-django-lookup releases = [ . sublime_text = * tags = 1B ] . name = Django Manage Commands details = https://github.com/vladimirnani/DjangoCommands labels = [ Django python web management ] releases = [ . sublime_text = <3000 tags = st2- . sublime_text = >=3000 tags = st3- ] ] 

Some corner cases:
 { "a": "'...'", "b": "string which ends with a space ", "cd": "\n", "e ": "3", "dirs": [ ["Doc,Scans", ".t'xt"] ], "node": null, "n" : "N", "files": [], "f": "[]", "ff": [ [] ], "products": {} } 
 a = ''...'' b = 'string which ends with a space ' cd = "\n" 'e ' = '3' dirs = [ ['Doc,Scans', '''.t'xt'] ] node = N n = 'N' files = [] f = '[]' ff = [ [] ] products = {} 

Source: https://habr.com/ru/post/419361/


All Articles