Versatile Separated Values (VSV)

Started by Den, 2017-Nov-12 06:05

Previous topic - Next topic

Den

Versatile Separated Values (VSV)

Official VSV website @ https://ieants.cc/code/vsv/

Proposal: A versatile, efficient, unambiguous, standardized, regular, simple text format for creating tables, lists, configuration files, and hierarchy containers, that's easily read and created by both humans and machines, that supports many variations for any personal style, preferences, and protocols. Can accept any nonspace character (including comma, colon, tab, asterisk, etc.) as delimiter automatically without user input (no annoying popups or options to fill in).

The same simple algorithm will accept almost any delimiter you want. You want commas like CSV? No problem. Or fields separated by tab (TSV)? Sure. How about *NIX files that use colons? We'll take it. Want to mix them up in the same table or file? Go ahead. These simple rules mean it's very easy for both humans and machines to encode and decode VSV files.

Since the rules are simple, consistent, and regular, VSV can be adopted for any purpose. Such as HTML lists and tables, media playlist, subtitle, real-time captioning, site summary syndication, configuration files, object and array notation, page markup, style sheets, notes, etc. The creator of VSV always writes notes and lists in VSV, and only uses the simple yet powerful VPL (VSV playlist) format in VLC media player (hundreds of .vpl files). VSV files take up much smaller space, to represent the same data compared to other formats, such as XML, JSON, RSS, XSPF, M3U, etc.

Moreover, VSV provides potentially greater functionality than other formats, due to versatility and extensibility for custom or vendor specified variables. For instance, VPL provides an easy way to load a list of files that only differ by incremental values (i.e. all episodes in all seasons of a show.) This would take up only simple three lines in VPL; whereas other formats would take dozens, if not hundreds of lines. That's because in other formats, each episode must be declared separately. Fortunately, VSV (thus VPL) are humane, dynamic formats that allow programs to interpret and execute the data as efficiently as possible.

Exporting to VSV (creating files)

A VSV file consists of two types of rows: header and data.

Rows are separated by newline. 

Creating Header Rows

Header rows are optional.

A header row consists of one or more header field. Each header field is enclosed by any of these double matching bracket types:
[[]]
{{}}
(())
<<>>


A header row is identified when, ignoring the opening spaces of a row, the first two characters of a row are any consecutive double opening brackets, as listed above.

Distinct header fields may use the same or different brackets types. Different bracket types may be employed on the same header row and across rows.

When exporting to a VSV file, characters that are found within a header field must not be used as enclosing brackets for that field. Choose a bracket not found in that inside text to surround that field.

Any text in a header row that is not within the legal boundaries of a header field is ignored. That includes improper closing of brackets, and text outside the brackets. This side effect may be surreptitiously used as comments for your text file, but should be used with care, in order to be properly rendered by plugins. (That is, a plugin cannot safely interpret if your intent is a comment or an error, a typo.)

Creating Data Rows

Data rows (non headers) must be led by an explicit nonspace character, called delimiter. All leading spaces are ignored until a nonspace character is found, which becomes the delimiter for that row.

Values for a data row are placed between two delimiters. The first occurrence of a delimiter on that row is not counted as part of the values. To prevent delimiter-value collision, the delimiter should be a character that is not found in the values' texts of that row.

A null value has zero length, signified by consecutive delimiters with nothing in between them.

A delimiter at the end of the line after the final value is optional, unless the final value is a null value.

Each row may have its own distinct delimiter. A text file may have distinct rows with their own delimiters. Creators can use the same delimiters or mix them for different rows, as long as the desired values on that row are distinguishable (i.e. to prevent delimiter-value collision.)

When exporting to a VSV file, characters that are found in the values of a given row must not be used as delimiter for that row. Choose a character not found in that row's values as the delimiter for that row.

  • Space and newline cannot be used as delimiter. Any other single character may be used.
  • Letters and numbers may be used as delimiters, but are not recommended.
  • Avoid using header field brackets as data row delimiters. Nevertheless, single bracket at beginning of a row should be read as a legal delimiter.
  • Creators may have their own preferred delimiters. Common delimiters to use:
,
:
|
;
*
-
@
#
%
~
`
TAB


Importing VSV (reading files)

The following rules dictate how plugins and code should read and interpret VSV files.

Rows are separated by newline. Leading spaces on each row are discarded and ignored.

After discarding all leading spaces, if the first two characters of a row are identical opening brackets, this is a header row. Else it is a data row.

Reading Header Rows

Header fields must be enclosed by both an opening and a closing matching double brackets. Any other text on a header row is discarded and ignored.

Reading Data Rows

The first nonspace character of a data row is its delimiter. The values of this row are stored between two delimiters or the end of line. A value can have zero length, or null value. There is no value between a line-ending delimiter and end of line (it doesn't count as another value, not even null value).

In PHP, use the explode() function to store a row's values into an array split by the delimiter. Likewise, in Javascript, use String.prototype.split(). For other languages, use a regexp to match the values separated by the delimiter.

Examples

Questions

How to handle values that contain newline? to create template of VSV code. or Self-modifying code. cf. <![CDATA[
Can it be used for objects or hierarchy? i.e. in place of JSON, XML, HTML
Can it be used as configuration file? cf. INI, CONF, PASSWD files
Can it be used as subtitle file? cf. SRT, VTT
Can it be used as playlist file? cf. PLS, M3U, XSPF
Can it be used as site summary syndication? cf. RSS, Atom
Support me on Patreon

I saw. I conquered. I came.


Den

#2
VSV Usage examples and comparison to other formats


VSV as Tabular Data

Double Matching Brackets are header fields (optional)
Everything else are data rows

Ex. When using the Comma , as delimiter, similar to CSV:

[tables=vsv]
((Name)) ((Score 1)) ((Score 2))
,BEAKL 8, 104, 132
,BEAKL 9, 120, 144
,BEAKL 10, 44, 99
[/tables]

NameScore 1Score 2
BEAKL 8 104 132
BEAKL 9 120 144
BEAKL 10 44 99


Ex. Can use any nonspace character as delimiter--lots of freedom:

[tables=vsv]
[[Name]] {{Age}} ((Gender)) <<Birthsign>>
,Hammie, 20.5, F ,Leo
-Chow, Vivian-40-F -Scorpio
:Amuseum:25:M:Scorpio
*Shena'Fu *18+5/12 *F *Sagittarius
|Grndr-1245|21 months||Pisces
Fairy Nuff 14 K N/A Gemini
[/tables]

NameAgeGenderBirthsign
Hammie 20.5 F Leo
Chow, Vivian40F Scorpio
Amuseum25MScorpio
Shena'Fu 18+5/12 F Sagittarius
Grndr-124521 monthsPisces
Fairy Nuff14 KN/AGemini



VSV as Linux password file

The Colon :  starts each line and separates each field

:smithj:x:561:561:Joe Smith:/home/smithj:/bin/bash


VSV as configuration file

Double Square Brackets [[ starts each section
Unclosed Double Brackets are comments and help
The Equal = starts each line and separates the setting key from its value

[[General]]
((display options: fullscreen, windowed, windowedmax
=display=fullscreen
=width=1920
=height=1080


VSV as XML replacement

Double Angled Brackets << as tags
Close innermost tag with the Slash / inside double brackets
Data rows as attributes and content
Use spaces to indent

<<div>>
 <<p>>
  ~To: Tove
 <</>>
 <<p>>
  ~From: Jani
 <</>>
 <<h2>>
  ~Reminder
 <</>>
 <<p>>
   ~Meeting this weekend!
  <<span>>
   =style=color: red
   ~ Don't forget!
  <</>>
  <<p>>
   ~-J
  <</>>
 <</>>
<</>>


VSV as Objects and Arrays

Double Curly Brackets {{ as Objects
Double Square Brackets [[ as Arrays
Close innermost object or array with the Semicolon ; inside double brackets
Data rows as properties
Use spaces to indent

((probably harder to read than JSON, but has similar capabilities
((however, JSON doesn't allow comments, like these first two lines
{{}}
 {{menu}}
  ~id~file
  ~value~File
  {{popup}}
   [[menuitem]]
    {{}}
     ~value~New
     ~onclick~CreateNewDoc()
    {{;}}
    {{}}
     ~value~Open
     ~onclick~OpenDoc()
    {{;}}
    {{}}
     ~value~Close
     ~onclick~CloseDoc()
    {{;}}
   [[;]]
  {{;}}
 {{;}}
{{;}}


VSV as Hierarchical Containers

Header rows for comments and informational purposes
Data rows for containers xor elements, depending on delimiter
Close innermost container with appropriate closing delimiter
Use spaces to indent

Delimiter to denote container types:
{ Class or hashtable
[ Array or list
( Function or code block
< Attributes or arguments

Other delimiters denote child non-container elements

<< webpage markup language (cf. XML example above)
{div
   {p
      $ To: Tove
   }
   {p
      $ From: Jani
   }
   {h2
      $ Reminder
   }
   {p
      $ Meeting this weekend!
      {span
         <
            ~ style ~ color:red
         >
         $ Don't forget!
      }
   }
   {p
      $ -Jani
   }
}
((programming object notation (cf. JSON example above)
{
   {menu
      $id$file
      ,value,File
      {popup
         [menuitem
            {
               ,value,New
               ^onclick^CreateNewDoc
            }
            {
               ,value,Open
               ^onclick^OpenDoc^file
            }
            {
               ,value,Close
               ^onclick^CloseDoc^file
            }
         ]
      }
   }
   (OpenDoc
      <
         = file = File
      >
      $contents = io.open(file);
      $return contents;
   )
}

Support me on Patreon

I saw. I conquered. I came.

Den

#3
Project via git:
Git repo @ bitbucket.org: https://bitbucket.org/Shenafu/vsv/

Examples of utilizing Javascript to interpret VSV into HTML lists, tables, XML/HTML, and JSON:
https://ieants.cc/code/vsv/
Support me on Patreon

I saw. I conquered. I came.

Den

#4
VSV as Subtitle Format

(research and development phase)

File extension: *.vst

Criteria

- simple, yet extensible
- basic features, incl. time start and end, text to display
- advanced features, incl. styling, position, angle, color, classes, scrolling (ala marquee),
- optional metadata and general options, incl. language and encoding, movie metadata, author and staff of subtitle (e.g. translators, timers)

The wonderful thing about VSV is simple, yet extensible and universal. Thus both simple and complex subtitles can be created in VSV. Simple ones will look simple; complex ones will also look simple without clutter or different look or rules. (Cf. XML is a cluttered format. VTT has different syntax for different sections.)

Sections

A subtitle file is divided into sections marked by headers (which are not case sensitive). All sections are optional. If a file begins with no headers, it is implied to begin in the Main section. A section type can appear multiple times in the same file.

VST files may have a [[VST]] header at the first bytes of the file. This is recommended in order for programs to instantly recognize it as a VST file. Note however this header doesn't begin a true section like the other headers below.

The [[Main]] section holds the subtitles texts, timing, and additional information pertaining to that subtitle segment.

The [[General]] section holds the metadata and general options.

The [[Style]] section defines styles in the same format as CSS.

Data fields

Data rows holds one or more data fields or values. For rows that contain more than one field, the first is the property that defines the rest of the fields on that row.

The \ backslash is the escape character for advanced features. Including new lines of a multiline subtext, and inline styling. To print the backslash itself, use double backslash \\. The \ must not be used as delimiter.

Subtitle data

Data rows in the main section hold the subtitle data that will be displayed in a video. The general layout is a time or frame row, followed by one or more rows that describe a subtitle line, including text and additional optional properties, such as style and class. That means a time or frame row signals the beginning of a new subtitle segment.

----

The 't' property means time, and is followed by one or two data fields that represent the start and end times of a subtitle line. The time data is in the format HH:MM:SS.mmm. HH: can be omitted to imply zero hours. .mmm can be omitted to imply zero milliseconds. The start time must be included. If the end time is omitted, the subtitle will be displayed until the end of the video.
Ex.
,t,12:27,12:38

----

The 'f' property means frame, and is followed by one or two data fields that represent the start and end frames of a subtitle line. The frame data is an integer from 0 to the last frame of the video. The start frame must be included. If the end frame is omitted, the subtitle will be displayed until the end of the video.
Ex.
,f,335,518

----

The 's' property defines the text to be displayed.

Every additional data field starts on a new line when displayed on the video; i.e. multiline. That is, whenever a delimiter is repeated on the same data row, it starts a new line in the video. New lines can also be denoted with \n.

To prevent delimiter-value collision, it is behooved to use a delimiter not found in the particular text for that row, and generally not normally found in your language's everyday grammar.

Ex.
In both examples, the delimiter is tick `.
Single line
`s`Stop! In the name of love!

Multiline
`s`Stop!`In the name of love!
`s`Stop!\nIn the name of love!

----

The 'c' property declares the class of this particular subtitle segment. Classes are the same concept as HTML classes. So they can be used as expedient access to various features, including styling, positioning, etc. These styles are defined in another section of the file or in a separate .css file.

Ex.
,s,Stop! In the name of love!
,c,music


----

The 'func' properties allows passing special commands to the media player, including vendor specific options.
----

TBD: additional properties, including position, color, scrolling, angle, etc.

TBD: markup for inline styling a substring of a line, incl. bold, underline, italicize (e.g. *, _, /). To print these exact characters, escape it with backslash (e.g. \*, \_, \/)

TBD: properties for general options and metadata

TBD: considerations for real-time caption, streaming

TBD: embed media: images, video, audio, 3d models, transformations, effects

TBD: commands and scripting: pause, resume, include external files, shift time or frames for text and audio (e.g. fix out of sync)

TBD: plugins for media players: VLC via Lua,

TBD: develop and test VST using a HTML5 player




Full Examples

Simple files


[[VST]]
,t,01:11.704,01:13.006
`s`All right, let's go. I'll give you half an hour.

,t,01:16.209,01:17.777
`s`What?

,t,01:18.845,01:20.547
`s`Are you serious?

,t,01:20.547,01:23.750
`s`Look, Jerry, we have to have sex to save the friendship.

,t,01:24.951,01:29.489
`s`Sex, to \*save\* the friendship.

,t,01:31.057,01:35.328
`s`Well if we have to, we have to.



Complex files


[[VST]]
[[Style]]
`.jerry`color: green
`.elaine`color: yellow


[[Main]]
,t,01:11.704,01:13.006
`s`All right, let's go. I'll give you half an hour.
,c,elaine

,t,01:16.209,01:17.777
`s`What?
,c,jerry

,t,01:18.845,01:20.547
`s`Are you serious?
,c,jerry

,t,01:20.547,01:23.750
`s`Look, Jerry, we have to have sex to save the friendship.
,c,elaine

,t,01:24.951,01:29.489
`s`Sex, to \*save\* the friendship.
,c,jerry

,t,01:31.057,01:35.328
`s`Well if we have to, we have to.
,c,jerry



[[VST]]
[[Style]]
`.aside`vertical-align: top`margin-top: 1em
`.music`font-style: italic
`.music::before`content: "#"
`.music::after`content: "#"

[[Main]]
,t,01:31.057,01:35.328
,s,Stop! In the name of love!
,c,music

,t,01:31.057,01:35.328
`s`Stop! In the Name of Love`by Diana Ross and The Supremes
,c,aside



Support me on Patreon

I saw. I conquered. I came.

Den

#5
VSV as Playlist Format

(coding and testing phase)

File extension: *.vpl

Criteria

- simple, yet extensible
- basic features, incl. file, title, artist, duration
- advanced features, incl. repeat amount, gain, media start and end times, resume from last media played, associated files (such as subtitle or lyrics)
- optional metadata and general options

Sections

A playlist file is divided into sections marked by headers (which are not case sensitive). All sections are optional. If a file begins with no headers, it is implied to begin in the Main section. A section type can appear multiple times in the same file.

The [[Main]] section holds the list of media, including their filenames and other specific data.

The [[General]] section holds the metadata and general options.

Playlist data

Data rows in the main section hold the playlist data. The general layout is a file row, followed by one or more rows that describe a file, including title, artist, duration, and additional optional properties, such as style and class. That means a file row signals the beginning of a new file subsection.

Some properties will hold data that will be applied for all subsequent files. So that one may apply the same title and artist for many files without the need to repeat. See below for these properties.

----

The 'f' property means file name, and is followed by a field that refers to a video file or another playlist file. The file can point to a local computer or remote address, such that the media player can access that file. As such, the file can be relative path, absolute path, or URL that can be handled by the media player.

If 'pathAll' is defined, every subsequent file is affixed by that property. The first data is prefix (will precede the file name), and second data is suffix (will follow the file name).

Ex.

`f`video-01.mp4
`f`video-02.mp4
`f`video-03.mp4
`f`video-04.mp4


`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.01.rmvb
`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.02.rmvb
`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.03.rmvb
`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.04.rmvb


'pathAll'file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/'.rmvb

`f`Cooking.Beauties.01
`f`Cooking.Beauties.02
`f`Cooking.Beauties.03
`f`Cooking.Beauties.04


----

The 'fn' property creates a list of files using sequential numbers. The fields are the starting and ending numbers. If 1st field is omitted, starting number set to 1. If 2nd field is omitted or less than starting number, end number set to starting number. If you need to pad numbers with leading 0s, use 'pad' property before 'fn'

Ex.

-fn-1-154


This creates all the files from between 1 and 154. If pathAll property is also defined, numbers are inserted accordingly.

Ex.

,pathAll,file:///f:/media/anime/Major/Major ,.mp4

-pad-3
-fn--154


The file names that will be added to the playlist are:
file:///f:/media/anime/Major/Major 001,.mp4
file:///f:/media/anime/Major/Major 002,.mp4
file:///f:/media/anime/Major/Major 003,.mp4
...
file:///f:/media/anime/Major/Major 154,.mp4

Because of pad 3, the numbers are actually 001, 002, ... , 099, 100, ... , 154. Without pad, the numbers will be 1, 2, 3, ... 98, 99, 100.

----

The 'pad' property pads numbers with leading 0s for 'fn' property. That is, if the amount of digits in a number are shorter than pad, then extra 0s are added to the left until the number has that many digits.

See example above, in 'fn' property.

----

The 's' property means subtitle file, and is followed by a field that refers to a subtitle file or lyrics file.

Unfortunately, VLC only accepts local OS format to the subtitle file's path.


`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.01.rmvb
`s`f:\media/Chinese\-Variety\Cooking Beauties 2018\Cooking.Beauties.01.vst


Note difference in file path format for VLC.

----

The 'd' property means duration. Format depends on media player. VLC supports seconds.

`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.01.rmvb
`d`2700


----

The 't' property means title that will be displayed on the playlist panel or window, if supported by the media player.

`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.01.rmvb
`t`Cooking Beauties 2018 - EP 01


----

The 'a' property means artist.

`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.01.rmvb
`a`TVB


----

The 'p' property means publisher.

`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.01.rmvb
`p`TVB


----

The 'desc' property means description. A blurb to describe the media.

`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.01.rmvb
`desc`Beautiful women celebrities compete in cooking contest. But will their cooking be delicious or horrendous?


----

The 'id' property sets the track's id. Usage depends on whether in 'idAuto' or 'idManual' mode.

The 'idAuto' property sets id assignment to auto. This is default mode, and doesn't have to used unless you want to return to auto mode from 'idManual'.

The 'idManual' property sets id assignment to manual.

In auto mode, each file on the playlist is automatically assgined an id, starting at 1 and incremented by 1 as new files are added. Use the 'id' property to assign a file's id to that value and start counting from there for subsequent files.

In manual mode, each file has id 0 unless set with 'id' property.


`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.01.rmvb
`id`1


----

The 'startPlayId' property picks the id of the file to start playing when the playlist is first loaded. In the id auto mode, the id starts at 1 to the maximum number of files on the list. The default value for startPlayId is 1--the first item on the playlist; a value that doesn't match any id will start playing at first file.


`startPlayId`3

`f`video-01.mp4
`f`video-02.mp4
`f`video-03.mp4
`f`video-04.mp4


will start playing at video-03.mp4.

----

The 'startPlayFile' property matches the filename to start playing when the playlist is first loaded. The data supplied can be a partial file name.

'startPlayFile' is not processed if 'startPlayId' is also supplied.


`startPlayFile`video-04

`f`video-01.mp4
`f`video-02.mp4
`f`video-03.mp4
`f`video-04.mp4


will start playing at video-04.mp4.

----

The 'startHere' property sets the current file id as the first file to be played. The last command found in the playlist between 'startHere' or 'startPlayId' will take priority; either of these commands will take priority before 'startPlayFile'.


`f`video-01.mp4
`f`video-02.mp4
`f`video-03.mp4
'startHere
`f`video-04.mp4


----

The 'func' properties allows passing special commands to the media player, including vendor specific options.

----

Global properties

The following properties apply the same data to all subsequent files if not specifically set for those files, until that property is invoked again to assign new data. Basically a fast way to assign the same data to an entire group of files, without repetitive text cluttering the playlist file, nor repetitive cut and paste.

Global properties are immediately assigned to any new file declared by 'f'.

'tAll' : same title
'aAll': same artist
'pAll': same publisher
'dAll': same duration
'descAll': same description
'pathAll': same path affixes

----

Substitution

Data can also be substituted into other data by enclosing the corresponding property name inside double brackets (any of the header brackets are valid).

Replacements should be defined beforehand.

{{f}}: substitute file (full URL)
{{fpath}}: substitute file path (path to directory without protocol or filename)
{{ffull}}: substitute file name with extension
{{fname}}: substitute file name without extension
{{fext}}: substitute file extension (with leading dot)
{{s}}: substitute subtitle file (full URL)
{{t}}: substitute title
{{a}}: substitute artist
{{p}}: substitute publisher
{{d}}: substitute duration
{{id}}: substitute id
{{desc}}: substitute description

{{tAll}}: substitute global title
{{aAll}}: substitute global artist
{{pAll}}: substitute global publisher
{{descAll}}: substitute global description


`tAll`Cooking Beauties

`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.01.rmvb
`t`{{tAll}}`part 01

`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.02.rmvb
`t`{{tAll}}`part 02


will become:
Cooking Beauties - part 01
Cooking Beauties - part 02


`f`...
`a`S.H.E
`desc`Enjoy new hit single by {{a}}


In this case, `a` should be defined before `desc` can substitute it in. Else {{a}} will just be empty. You can also define global properties instead, also beforehand. So the following will also work:


`aAll`S.H.E

`f`...
`desc`Enjoy new hit single by {{a}}


In this case, `f` will immediately receive global properties, such as `aAll` before it. This implicitly defines `a` for this file. Thus, {{a}} will be available for substitution.

To represent a property that will be substituted later, enclose the substitution in another layer of double enclosed brackets.


`tAll`Cooking Beauties`{{{{id}}}}

`f`Cooking.Beauties.01.rmvb
`f`Cooking.Beauties.02.rmvb


will become:
Cooking Beauties - 1
Cooking Beauties - 2

In this case, 'tAll' has a code {{{{id}}}}. When this line is processed, this will reduce it to just {{id}}. When 'f' is processed, 'tAll' is passed down and also processed, but now with just {{id}}, which of course refers to the current file's id.

----

Variables

The 'var' property sets custom variables that can be substituted into other data by enclosing colon : and variable name in double brackets.


:var:baseTitle:Cooking Beauties
'tAll'{{:baseTitle}}'{{{{id}}}}
'desc'{{:baseTitle}} features {{a}}


----

Calculations

Do calculations on the spot. Enclose equal sign = and the equation in double brackets.

TBD: Notation used for math and logic. Presumably basic arithmetic + - * / are shared among most programming languages.

TBD: How are variables used? Use variables instead of nested brackets.


Examples:

't'{{={{id}}-1}}

'tAll'{{{{={{id}}-1}}}}

(( Recommended method below, using variables to store equations
:var:newid:={{id}}-1
`tAll`Girls High School Mystery Class`{{{{:newid}}}}


----

Full Examples

Simple playlists

`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.01.rmvb
`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.02.rmvb
`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.03.rmvb
`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.04.rmvb


Complex playlists

`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.01.rmvb
`t`Cooking Beauties 2018 - EP 01
`d`2700
`a`TVB
`p`TVB
`desc`Beautiful women celebrities compete in cooking contest. But will their cooking be delicious or horrendous?

`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.02.rmvb
`t`Cooking Beauties 2018 - EP 02
`d`2700
`a`TVB
`p`TVB
`desc`Beautiful women celebrities compete in cooking contest. But will their cooking be delicious or horrendous?

`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.03.rmvb
`t`Cooking Beauties 2018 - EP 03
`d`2700
`a`TVB
`p`TVB
`desc`Beautiful women celebrities compete in cooking contest. But will their cooking be delicious or horrendous?

`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.04.rmvb
`t`Cooking Beauties 2018 - EP 04
`d`2700
`a`TVB
`p`TVB
`desc`Beautiful women celebrities compete in cooking contest. But will their cooking be delicious or horrendous?


Neater with *All properties and fn:

:var:baseTitle:Cooking Beauties 2018
,tAll,{{:baseTitle}},{{{{id}}}}
`aAll`TVB
,pAll,TVB
`descAll`Beautiful women celebrities compete in cooking contest. But will their cooking be delicious or horrendous?
`commentAll`Beautiful Cooking returns to a third season after nine years of hiatus.

'pathAll'file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.'.rmvb

-pad-2
-fn-1-21


,startPlayId,2

,tAll,Asheron's Call 2 Livestream ft. Shena'Fu,part {{{{id}}}}

,pathAll,https://www.youtube.com/watch?v=

`f`EZfbsT8FAQ4
`f`RysXIquKQwY
`f`iG-s9QhaQZQ
`f`NySeXRmeAEg


Multiple levels of substitution:

{{Main}}

`tAll`Cooking Beauties 2018`{{{{id}}}}
`aAll`TVB
,pAll,TVB
`descAll`Beautiful women celebrities compete in cooking contest. But will their cooking be delicious or horrendous?``{{{{t}}}} features {{{{a}}}}.
`commentAll`Beautiful Cooking returns to a third season after nine years of hiatus.

`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.01.rmvb
`d`2700

`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.02.rmvb
`d`2700

`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.03.rmvb
`d`2700

`f`file:///f:/media/Chinese/-Variety/Cooking Beauties 2018/Cooking.Beauties.04.rmvb
`a`[[aAll]]`beauties
`p`[[pAll]]`partners
`d`2700


----
TBD: append supplementary playlists; should also append indexes

TBD: auto-generated files, i.e. 'smart' playlists. e.g. generate incremented ids in filenames (done); get all files in directory based on criteria

TBD: plugins for media players: Winamp

Plugins

VPL playlist can be loaded in VLC via Lua extension:
https://bitbucket.org/Shenafu/vsv/src/master/playlist/
Support me on Patreon

I saw. I conquered. I came.

Den

#6
Prototype for loading playlist in VLC is successful and powerful. Gives hope for loading subtitles as well.
Support me on Patreon

I saw. I conquered. I came.

Den

#7
2018/11/4

; vpl ; added property ; fn ; sequential numbers in file names
; vpl ; added property ; pad ; digits to pad for fn
Support me on Patreon

I saw. I conquered. I came.

ADMIN

test upload as attachments on this forums.
.vsv
.vpl
.vst

Den

Support me on Patreon

I saw. I conquered. I came.

Den

#10
RSS-like format for site summary syndication. Resembles much like .vpl . in fact, VPL may be extended or substituted for RSS. or perhaps a slightly altered format, dubbed .vsy

Example:

[[VSY]]

[[Channel]]
`f`http://www.example.com/main.html
`t`VSY Title
`desc`This is a description of the channel
`cr`copyright
`db`Mon, 06 Sep 2010 00:01:00 +0000
`dp`Sun, 05 Sep 2010 00:01:00 +0000
`ttl`1800
`lang`en-us
`a`Author Info
`p`publisher
`var`type`serial
`var`email`admin@mysite.com
`var`content`The Sunset Explorers share tips, techniques and recommendations for great hikes and adventures around the United States. Listen on\n<a href="https://www.apple.com/itunes/podcasts/">Apple Podcasts</a>.
`var`encf`http://example.com/podcasts/everything/AllAboutEverythingEpisode4.mp3
`var`encd`498537
`var`enctype`audio/mpeg


[[Items]]
`f`http://www.example.com/item.html
`t`VSY Item
`desc`This is a description of the item
`dp`Mon, 06 Sep 2010 00:01:00 +0000
`d`1079
`guid`7bd204c6-1655-4c27-aeee-53f933c5395f



where `var` fields is used to extend nonstandard, extraneous, or emergent data, created by vendors, et al.

Compare the RSS format in the spoiler:
[spoiler]
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
<title>Hiking Treks</title> <link>https://www.apple.com/itunes/podcasts/</link>
<language>en-us</language>
<copyright>© 2019 John Appleseed</copyright>
<itunes:author>The Sunset Explorers</itunes:author>
<description> Love to get outdoors and discover nature's treasures? Hiking Treks is the show for you. We review hikes and excursions, review outdoor gear and interview a variety of naturalists and adventurers. Look for new episodes each week.
</description>
<itunes:type>serial</itunes:type>
<itunes:owner> <itunes:name>Sunset Explorers</itunes:name>
<itunes:email>mountainscape@icloud.com</itunes:email>
</itunes:owner>
<itunes:image
href="https://applehosted.podcasts.apple.com/hiking_treks/artwork.png"
/>
<itunes:category text="Sports">
<itunes:category text="Wilderness"/> </itunes:category>
<itunes:explicit>false</itunes:explicit>
<item>
<itunes:episodeType>trailer</itunes:episodeType>
<itunes:title>Hiking Treks Trailer</itunes:title>
<description>
<content:encoded>
<![CDATA[The Sunset Explorers share tips, techniques and recommendations for great hikes and adventures around the United States. Listen on
<a
href="https://www.apple.com/itunes/podcasts/">Apple Podcasts</a>.]]>
</content:encoded>
</description>
<enclosure
length="498537"
type="audio/mpeg"
url="http://example.com/podcasts/everything/AllAboutEverythingEpisode4.mp3"
/>
<guid>aae20190418</guid>
<pubDate>Tue, 8 Jan 2019 01:15:00 GMT</pubDate>
<itunes:duration>1079</itunes:duration>
<itunes:explicit>false</itunes:explicit>
</item>
</channel>
</rss>
[/spoiler]

again, VSV/VSY is more easily legible and processed by humans and computers alike, at half the size.
Support me on Patreon

I saw. I conquered. I came.

ADMIN

test upload as attachments on this forums.
.von
.vml

Den

VPL now calculates equations. Enclose equal sign = and the equation in double brackets.

for instance, to shift or adjust discrepancy between file ID and episode number.

(( Example:
(( Recommended method below, using variables to store equations
:var:newid:={{id}}-1
`tAll`Girls High School Mystery Class`{{{{:newid}}}}
Support me on Patreon

I saw. I conquered. I came.

Den

#13
VON now allows inline arrays.

What are arrays? Arrays are lists with indexes that are automatically incremented by one for each item in the list.

Unlike objects, these indexes do not have to be predefined. Therefore, one should be able to write lists in a very simple manner. Hence inline arrays.

However some arrays may cantain children that are themselves arrays or objects. These cannot be written as simple inline arrays.

So we devise several ways to write arrays in VON:


1. Inline array with no children that are arrays or objects, and whose parent is an array.

All list items are written on one line, in between square brackets []. A second delimiter must be introduced inside these brackets, and separate each item. Note the second delimiter must come after the opening bracket, but precede the first item. Space cannot be delimiter.

Ex. [parent
  [,item1,item2,item3]
]

In this example, the comma is used as the second delimiter.


2. Inline array with no children that are arrays or objects, and whose parent is an object.

These are the same as inline array described above in part 1. Except the first item becomes a key for the parent object, and is excluded from the list.

Ex. {parent
   [,key,item1,item2,item3]
}

In this example, the array is referenced via "key" from its parent. In JSON this is equivalent to:

{
   "key": [item1, item2, item3]
}


3. General array that can cover all cases, whether children are arrays or objects or neither.

Children that are arrays or objects are declared as you would normally, using the appropriate brackets.

Children that are neither are put in rows with delimiters except brackets. One or more items can be put in the same row.

Inline arrays can also be put on their own rows.

Ex. Array with mixed children


[
   [subArray
      ,0,5,2
   ]
   {subObject
     ,hp,51
     ,str,43
   }
   ,loner
   ,more,data,in,this,row
   [,inline,array]
]


Note the difference between the last two lines. The line ",more,data,in,this,row" creates a new index for each item separated by delimiter. But the next line "[,inline,array]" creates a single item child that is a subarray.

An output to debug this array may look something like this:

IndexData
0  [0,5,2]
1  { "hp": 51, "str": 43}
2  loner
3  more
4  data
5  in
6  this
7  row
8  [inline,array]



Support me on Patreon

I saw. I conquered. I came.

Den

#14
VON now allows inline objects.

What are objects? Objects contain pairs of data such that a key is associated with a value.

Some objects do not contain children objects or arrays. Thus one should be able to write simple objects in a very simple manner. Hence inline objects.

So we devise several ways to write inline objects in VON:



1. Inline objects with no children that are arrays or objects, and whose parent is an array.

All key=value pairs are written on one line, in between curly braces {}. A second delimiter must be introduced inside these braces, and separate each item. Note the second delimiter must come after the opening brace, but precede the first item. Space cannot be delimiter.

Ex.
[parent
  {,key1,value1,key2,value2}
]


In this example, the comma is used as the second delimiter. In JSON this is equivalent to:

[
   {
      "key1": "value1",
      "key2": "value2"
   }
]



2. Inline object with no children that are arrays or objects, and whose parent is an object.

These are the same as inline object described above in part 1. Except the first item becomes a key for the parent object, and is excluded from the rest.

Ex.
{parent
{,inlineobject,under,object,key2,value2}
}


In this example, the new object is referenced via "inlineobject" from its parent. In JSON this is equivalent to:

{
   "inlineobject": {
      "under": "object",
      "key2": "value2"
   }
}


Support me on Patreon

I saw. I conquered. I came.

Den

#15
VSV as PHP library

vsv class in PHP
MethodsUsage
 mapToArray  each row is saved in array. mainly helper function for other map functions
 mapToHash  each data row is saved as key => value
 mapToAtomic  each data value is saved in linear array
 mapFromVon  convert to PHP object


Note:
PHP handles arrays, stacks weirdly. Solution: recursively create objects and arrays.


Examples:
spl_autoload("vsv");

// beforehand, use curl or file_get_contents to retrieve text
...
$text = @curl_exec($ch);
$vsv = new vsv($text);
$output = $vsv->mapToHash();
print_r($output);

Support me on Patreon

I saw. I conquered. I came.

Den

Support me on Patreon

I saw. I conquered. I came.

Den

2022/03/16

Now VSV tables can have captions. Captions for a VSV table can be created in header fields when preceded by double ticks ``. A second double-ticks will signify the position of the caption. Use 'lcr' to align the caption left, center, or right, respectively. Use 'tb' to place the caption above or below the table, respectively. The default is 'ct'. A table may have more than one caption.

Ex.
((``Demo Caption``r)

will align the caption to the right.
Support me on Patreon

I saw. I conquered. I came.

Den

#18
How to approach a VSV-style markup languauge? So many out there: HTML/DOM, PDF/PS, TeX, Markdown, Wiki, OpenDocument .odf, etc.

Criteria:
  • simple, yet extensible
  • allow styling and scripting
  • headers, footers, titles, lists, tables, paragraphs, pages
  • fonts
  • embedded, media, images, video, audio, other documents
  • hyperlink
  • table of contents, annotations, bookmarks, etc.
  • printing
  • math, scientific
  • viewable from browser, like HTML, including plugin, library
    • probably just convert to DOM
  • compressable? archived?
  • metadata, title, author, language, encoding, doctype, copyright
  • variables, labels, references, functions
  • input mode, document, table, list


More sensible idea: use VON instead? In fact, many markup languages actually resemble hierarchical nature, with attributes and children items -- including XML (.odf, .html, ebooks), TeX, PS, etc. See also next post on how to handle tots and atts.

Under VON, the only thing that matters is giving the elements explicit names. For instance, paragraphs in HTML are <p></p>, but TeX uses \par
Support me on Patreon

I saw. I conquered. I came.

Den

#19
Re: VON attributes and children

VON containers (objects, arrays, functions) can have both attributes and children items. Thus they must be differentiated at the programming level. However this does not affect or change how VON is written. (Similar to how HTML is converted to DOM, doesn't change the rules of HTML.)

One way to differentiate attributes (atts) and children (tots) is for a parent container to have two implicit subcontainers, called tots and atts. (Sounds funny, but serious.) That will provide direct, unambiguous access to either when needed.

Apparently atts is an object that holds all the attributes. While tots, being the same container type as the parent container, holds all the children items. 

If parent container is array, then index 0 holds atts, and index 1 holds tots. Thus array[0] = {}, and array[1] = [].

If parent container is object, then keys "tots" and "atts" will hold respective data. Thus object.atts = {}, and object.tots = {}.

If parent container is function, atts are the arguments, and tots are the code block. Thus function(atts) {tots}.

A better way to represent arrays programmatically is actually as an object. It has atts as an object, and tots as an array. Nevertheless, the underlying code doesn't alter the VON definition of array.

So to quickly differentiate between arrays and objects in code, we also predefine a key called "vontype", which can be consulted as need. That is, a new array child may be defined in the code as { atts:{}, tots:[], vontype:"array"}; while a new object child may be defined in the code as { atts:{}, tots:{}, vontype:"object"}

Slight difference, but will be easier to manipulate the arrays and objects.

Also consider creating classes for atts and tots, to help navigate and find the individual items or attributes (for languages that support classes). Or create such static helper functions.

If necessary, parent objects and arrays may (in the future) contain other items besides atts and tots, especially at the programming level. For instance, maintaining a value of how deep into the hierarchy, to do stuff like indentation. Thus atts and tots would be safe from future expansion.
Support me on Patreon

I saw. I conquered. I came.

Den

#20
VML successfully derived from VON. First convert VSV file text into VON, then run it through VML recursive function to process it into whatever output, such as DOM. Conversion should be automatic, behind the scenes, without user interaction.

Ex. user converts VML to DOM:

myDocument = VSV.mapTo.vml(vsvText);


Example VML code in spoiler:

[spoiler]
(( VML (VSV markup language)
(( for displaying pages, including webpages, documents, printed paper
(( use leading spaces for indentation
(( use [ ] to create and close elements
(( use < > to start and end attributes definitions

[div
   [p
      $ To: Tove
   ]
   [p
      $ From: Jani
   ]
   [h3
      $ Reminder
   ]
   [p
      $ Meeting this weekend!
      [span
         <
            {:style:color:red:font-variant:small-caps:backgroundColor:cyan}
         >
         $ Don't forget!
      ]
      $ Or your ass is mine!
   ]
   [p
      $ -J
   ]
]
[/spoiler]

Noticeably, the elements of the documents are declared as arrays, and their tags are declared right after the opening square bracket.

The reason to use arrays is to allow unnamed text fragments to append easily. Object containers would not work, as they demand named keys. Keys with identical names would overwrite one another; thus losing data. Or have the user keep track of key names to ensure they don't repeat; however that is just not feasible expectation.

Previously, array under array did not save their key name. That is, something like
[
  [p

  ]
]
the p would just be ignored and lost forever. Fortunately, now the p is saved under key 'tag' in the object that represents and encapsulates the array. Remember, instead of straight array, we used an object to represent the array, and saved its children under object.tots. Well now, we can also save the lost key into something like object.tag. That way we can reference the key or tag later. BTW the tag should be saved in the child array's representative object.

Next to do is special handling of tables and list. To read the simple format of those data. Special tags: vsvTable, vsvList. But also allow more complex tables, list? How to mix simple and complex?
Support me on Patreon

I saw. I conquered. I came.

Den

#21
Created online editor to play and test VSV. Even the editor page itself was created in VML.

Obviously there's more to do to improve the editor. For one, differentiate the type of VSV content by opening header.

ex.

[[table]]
[[list]]
[[vml]]
[[von]]


To make the editor page work required enhancing the code for VON function containers. Hence even scripting works inside VML.

Ex.

      [script
         (onSubmit
            <,event>
            `var datext = document.getElementById("datext");
            `var value = datext.value;
            `console.log(datext.value);
            `var vml = VSV.mapTo.vml(value);
            `console.log(vml);
            `var results = document.getElementById("results");
            `results.innerHTML = "";
            `results.appendChild(vml);
            `return false;
         )
      ]


Then when we submit the form, call the function we just created:


      [form
         <
            ,id,daform
            ,onSubmit,return onSubmit();
         >
      ]


Therefore the editor page works purely from VML, instead of HTML.

See attached for the VML code of the editor page.
Support me on Patreon

I saw. I conquered. I came.

Den

#22
VML now accepts VSV-style tables and lists (as opposed to complex, hierarchal). Their element tags are vsvtable and vsvlist. Basically VSV-formatted elements will begin with 'vsv' in order for libraries to recognize and treat them specially. (Otherwise, complex tables and list can be created in hierachically through the VON, like HTML tables and lists. Although maybe there could be middle ground, half-simple / complex. )

Ex. vsvlist

[vsvlist
,milk
,,eggs
,,,,patties
((forgot
, ,
,fries
,hazelnut creamer
,,
,<a href="https://bitbucket.org/Shenafu/vsv/">Sliced bread</a>
, ,
]


Ex. vsvtable

[vsvtable
((``My VSV Table``r))
<<Name>> <<Sex>> <<Age>>
,data1,data2,data3
]


Ex. complex list and table in spoiler:
[spoiler]

[ul
[li
  ,milk
  [ul
   [li
    ,eggs
    [ul
     [li
      ,patties
     ] 
    ]
   ]
  ]
]
]



[table
[tr
  [th
   ,name
  ]
  [th
   ,sex
  ]
  [th
   ,age
  ]
]
[tr
  [td
   ,data1
  ]
  [td
   ,data2
  ]
  [td
   ,data3
  ]
]
]

[/spoiler]
Support me on Patreon

I saw. I conquered. I came.

Den

One idea for pseudo-simple tables. Beforehand, user must define the number of columns they want in the table. Default is 2, if not set by user. Then every data provided just fills cell by cell, row by row. When the amount of data in a row matches the column count, then move on to next row. Until all the data is incorporated. Of course, you can make a cell empty by writing empty strings or null values.

Also must declare how many header rows. Default is 0. Likewise, if enabled, data values become header cells, filling up to the column and header row limits. (in HTML, these are TH tags.) Then the rest is normal data, filled accordingly. (in HTML, these are TD tags.) Can use empty headers.

This way, data can be as simple or complex as you want. Series of simple data can be written as a simple list of values. Complex data can be child items, declared as sub-elements.

Called ftable for fill table. Fully functional in editor.

Ex.

[ftable
<
,columns,3
,headerRows,1
>
,Header 1,Header 2
[span
  ,complex Header3
]
,simple,row,here
,first column
,second column
[a
  ,complex third column is anchor element
]
]


Ex. try messing around with this ftable in the editor. modify the attributes settings. alter the data. create simple and complex data, and empty data.

[ftable
<
,columns,5
,headerRows,2
>
,header1,header2
,data1,data2
,data1,,,
[p
,new paragraph
[span
,this is a span
]
]
,data1,
[a
<#href#https://ieants.cc>
,new link
]
]


ftable will also accept vsvtable-style header rows and captions. Note only simple headers can created this way. Header rows created this way will not count against headerRows attribute. They will append a new row of headers, but will not interrupt the filling of the cells. They could also be used to create new header rows in the middle of a table.

In fact this may be the only way to create captions for ftables.

Ex.

[ftable
<
,columns,5
>
((``Caption``))
((Header1)) ((Header2))
((Header3)) ((Header4))
,data1,data2
,data3,data4
,data5,,,
]



Heck, try ftable or vsvtable within ftable.

[spoiler]


[div
[ftable
<
,columns,5
,headerRows,2
>
,data1,data2
,data3,data4
,data5,,,
[p
,new paragraph
[span
,this is a span
]
]
,data1,
[a
<#href#https://ieants.cc>
,new link
]
[ftable
<
,columns,5
,headerRows,2
>
,data1,data2
,data1,data2
,data1,,,
[p
,new paragraph
[span
,this is a span
]
]
,data1,
[a
<#href#https://ieants.cc>
,new link
]
[vsvtable

((``Demo``r))
[[Name]] {{Age}} ((Gender))
((each row of data can have different delimiter, no problem
,Hammie, 20.5, F
-Chow, Vivian-40-F
:Amuseum:25:M:
*Shena'Fu *18+5/12 *F
|Grndr-1245|21 months||

Fairy Nuff 14 K N/A
((``Guess these names :)``b))

]
]

]
[p
,outside parag
]

]


[/spoiler]
Support me on Patreon

I saw. I conquered. I came.

Den

#24
Successfully sent VSV block via Node.js via Pug.

First, each HTML page must include vsv.js in the head, in order to transform VSV into DOM in the client browser.

VSV block should be sent inside a script element. This script will call VSV.mapTo.autoScript(). This function will automatically determine the VSV type (is it table, list, VML?), then insert it into the DOM before the current script element.

The custom filter for Pug looks like this. But first clean up the text so it escapes the brackets that are critical to VSV as the text is passed through the network. Backticks in javascript maintain the multiline text; so they should also be escaped.

VSV.pugFilters = {
'vsv':function (text, options) {
return "<script>VSV.mapTo.autoScript(`" + text.replace(/([`{[(<])/g, '\\$1') + "`);</script>";
}
};


Simply pass this filter to render:

res.render(myDoc, {filters: VSV.pugFilters});


Inside a pug file, include with vsv filter, like so:

include:vsv /public/atable.vsv
include:vsv /public/alist.vsv
include:vsv /public/mydoc.vml


Inline VSV block can be created like so, with indentation:

:vsv
[[vsvlist]]
,almonds
,banana
,cream pie


The client browser will receieve a script element with the above inner text from our filter. Upon reception, the script will execute, thus adding our VSV into the DOM.
Support me on Patreon

I saw. I conquered. I came.

Den

Support me on Patreon

I saw. I conquered. I came.

Den

#26
Quote from: Den on 2022-Oct-15 01:47VON will be used to define custom frames in Shena'Fu's Card Creator

See https://ieants.cc/smf/index.php?topic=29.msg3088#msg3088

My decision to use VON for creating custom frames, I needed a way to implement conditionals (boolean logic) and results thereof. It just dawned on me, that this resembles functional programming languages, like LISP, etc.

This raises the question: can VON be suitable for full-fledged functional programming? It worked well for custom frames. Since the VSV/VON syntax and philosophy is very simple, clean, regular, and well-defined.

(Aside)

It's amazing how far we've gone from the original purpose of VSV, to branching into possibly full programming languages. All derived from two simple core concepts: rows and delimiters.
Support me on Patreon

I saw. I conquered. I came.