Awesome
PurC
PurC
is the prime HVML interpreter for C/C++ language.
Table of Contents
- Introduction
- Release Status
- Building PurC
- Using
purc
- Contributing
- Authors and Contributors
- Copying
- Tradmarks
Introduction
HVML
is a descriptive programming language proposed and designed by Vincent Wei,
who is the author of MiniGUI, one of the earliest open-source software projects in China.
PurC
is the acronym of the Prime HVML inteRpreter for C/C++ language
.
It is also the abbreviation of Purring Cat
,
while Purring Cat
is the nickname and the mascot of HVML.
The goal of PurC is to implement all features defined by HVML Specification V1.0 and all predefined dynamic objects defined by HVML Predefined Variables V1.0 in C language.
You can use PurC to run an HVML program or an HVML app by using the command line tool purc
,
or use PurC as a library to build your own HVML interpreter.
We release the PurC library under LGPLv3, so it is free for commercial use if you follow the conditions and terms of LGPLv3.
This is version 0.9.20 of PurC. By now, PurC provides support for Linux and macOS. The support for Windows is on the way. We welcome anyone to port PurC to other platforms.
To learn the basic concepts of HVML programming, please refer to the following tutorials or articles:
For the Chinese version, please refer to the following links:
For documents, specifications, and open-source software related to HVML, please refer to the following repositories:
- HVML Documents: https://github.com/HVML/hvml-docs.
- PurC (the Prime hVml inteRpreter for C language): https://github.com/HVML/PurC.
- xGUI Pro (an advanced HVML renderer based on WebKit): https://github.com/HVML/xGUI-Pro.
- HVML FPM (the FastCGI Process Manager for HVML): https://github.com/HVML/HVML-FPM.
For sample applications wrotten by using HVML, please refer to the following repository:
- HybridOS Samples: https://github.com/HybridOS2/HBDSamples.
Release Status
Building PurC
Note that, if you are seeking the pre-built packages for platforms such as Ubuntu, Deepin, Homebrew, and MSYS2, you can refer to the following page:
https://hvml.fmsoft.cn/software
Prerequisites
To build PurC from source code, please make sure that the following tools or libraries are available on your Linux or macOS system:
- The cross-platform build system generator: CMake 3.15 or later
- A C11 and CXX17 compliant compiler: GCC 8+ or Clang 6+
- Zlib 1.2.0 or later
- Glib 2.44.0 or later
- BISON 3.0 or later
- FLEX 2.6.4 or later
- Python 3 (Python 3.9.0 or later if you want to build the external dynamic variant object
$PY
to use Python in HVML). - Ncurses 5.0 or later (optional; needed by Foil renderer in
purc
) - SQLite3 3.10.0 or later (optional)
If you want to enable the remote data fetcher, the following libraries are needed too:
- libsoup2 or libsoup3
- libgcrypt
- libicu
- libgpg-error
- libunistring
- openssl
If you are using Ubuntu 22.04 LTS or other similiar Linux distribution, you can use the following commands to install all above dependencies:
$ sudo apt install gcc-12 g++-12 bison flex python3
$ sudo apt install zlib1g-dev libglib2.0-dev libncurses-dev libbison-dev libpython3-dev libsqlite3-dev
# For remote fetcher:
$ sudo apt install libsoup-3.0-dev libgcrypt20-dev libgpg-error-dev libicu-dev libunistring-dev libssl-dev
Although the port for Windows is still on the way, it is possible to build PurC on Windows 10 version 2004 or later: You can install WSL (Windows Subsystem for Linux) and a Linux distribution, e.g., Ubuntu, on your Windows system, then build PurC in the Ubuntu environment.
Building steps
We assume that you are using Linux.
After fetching the source of PurC, you can change to the root of the source tree, and use the following command line to build and install PurC:
$ cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPORT=Linux -B build && cmake --build build && sudo cmake --install build
The above command line consists of the following commands:
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPORT=Linux -B build
: Change to thebuild/
subdirectory and runcmake
to generate the building files to build PurC. Note that this command uses the following options:-DCMAKE_BUILD_TYPE=RelWithDebInfo
: Specify the building type asRelWithDebInfo
. You can also useDebug
,Release
, and other options supported bycmake
.-DPORT=Linux
: Tellcmake
that you are building PurC for an operating system based on the Linux kernel. Use-DPORT=Mac
if you are using macOS.-B build
: Generate building files in thebuild/
subdirectory.
cmake --build build
: Build PurC in thebuild/
subdirectory.sudo cmake --install build
: Install PurC from thebuild/
subdirectory.
You can also use the following commands to build and install PurC step by step:
$ cd <path/to/the/root/of/the/source/tree/of/PurC>
$ rm -rf build/
$ mkdir build/
$ cd build/
$ cmake -DCMAKE_BUILD_TYPE=Release -DPORT=Linux ..
$ make -j4
$ sudo make install
If you'd like to use clang
llvm
instead of make
to build PurC,
you can use the following commands:
$ cd <path/to/the/root/of/the/source/tree/of/PurC>
$ cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPORT=Linux -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -Bbuild -GNinja && ninja -Cbuild && sudo ninja -Cbuild install
If you'd like to use ninja
instead of make
to build PurC,
you can use the following commands:
$ cd <path/to/the/root/of/the/source/tree/of/PurC>
$ cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPORT=Linux -Bbuild -GNinja && ninja -Cbuild && sudo ninja -Cbuild install
Note that you might need to remove the build/
directory first if there is already one.
By default, the above commands will build PurC and install the headers, libraries, executables,
and some documents to your system (under the /usr/local/
directory if you are using a Linux system).
When using make
, you can use DESTDIR
to specify an alternative installation directory:
$ make DESTDIR=/package/stage install
When using ninja
, you can also use DESTDIR
to specify an alternative installation directory:
$ DESTDIR="/package/stage" ninja -Cbuild install
Environment Variables
PurC uses the following environment variables for different purposes:
PURC_DVOBJS_PATH
: the path to save the shared modules for external dynamic objects.PURC_EXECUTOR_PATH
: the path to save the shared modules for external executors.PURC_FETCHER_EXEC_PATH
: the path to save the executable program of PurC Fetcher.PURC_USER_DIR_SUFFIX
: The directory suffix for the user.PURC_LOG_ENABLE
:true
if enabling the global log facility.PURC_LOG_SYSLOG
:true
if enabling to usesyslog
as the log facility.
Using purc
The following sections assume that you have installed PurC to your system,
and the command line tool purc
has been installed into /usr/local/bin/
.
Make sure that you have added /usr/local/lib
to /etc/ld.so.conf
and run sudo ldconfig
command,
in order that the system can find the shared library of PurC you just installed into /usr/local/lib
.
Run a single HVML program
Please save the following contents in a file named hello.hvml
as your
first HVML program in your working directory:
<!DOCTYPE hvml>
<hvml target="void">
$STREAM.stdout.writelines('Hello, world!')
</hvml>
To run this HVML program, you can use purc
in the following way:
$ purc hello.hvml
You will see that your first HVML program prints Hello, world!
on your terminal and quit:
Hello, world!
You can also run this HVML program directly as a script if you prepend the following line as the first line in your HVML program:
#!/usr/local/bin/purc
After this, run the following command to change the mode of the file to have the executing permission:
$ chmod +x hello.hvml
then run hello.hvml
directly from the command line:
$ ./hello.hvml
Run a HVML program with errors or exceptions
Please save the following contents in a file named error.hvml
in your working directory:
<!DOCTYPE hvml>
<hvml target="void">
$STREAM.stdout.writelines('Hello, world!)
</hvml>
We missed the second single quote of Hello, world!
in the code above.
The interpreter will exit with a nonzero return value if you run purc
without any options:
$ purc error.hvml
$ echo $?
1
You can run purc
with the option -v
for a verbose message:
$ purc -v error.hvml
purc 0.9.20
Copyright (C) 2022, 2023 FMSoft Technologies.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Failed to load HVML from file:///srv/devel/hvml/purc/build/error.hvml: pcejson unexpected eof parse error
Parse file:///srv/devel/hvml/purc/build/error.hvml failed : line=7, column=1, character=0x0
This time, purc
reported the error it encountered when it was parsing the HVML program: the wrong line and column.
If you change the program to add the missing single quote, purc
will be happy to execute the HVML program.
For an uncaught runtime exception, purc
will dump the executing stack.
For example, you can save the following program as exception.hvml
:
<!DOCTYPE hvml>
<hvml target="void">
<iterate on 0 onlyif $L.lt($0<, 10) with $DATA.arith('+', $0<, 1) nosetotail >
$STREAM.stdout.writelines("$0<) Hello, world! $CRTN.foo")
</iterate>
</hvml>
This HVML program refers to an inexistent property (foo
) of $CRTN
.
Run purc
to execute this HVML program with -b
option, it will report the executing stack:
$ purc -v exception.hvml
purc 0.9.20
Copyright (C) 2022, 2023 FMSoft Technologies.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Executing HVML program from `file:///srv/devel/hvml/purc/build/exception.hvml`...
The main coroutine terminated due to an uncaught exception: NoSuchKey.
>> The document generated:
>> The executing stack frame(s):
#00: <iterate on=0 onlyif=$L.lt( $0<, 10 ) with=$DATA.arith( "+", $0<, 1 ) nosetotail>
ATTRIBUTES:
on: 0
onlyif: true
with: 1L
CONTENT: `NoSuckKey` raised when evaluating the expression: $STREAM.stdout.writelines( "$0<) Hello, world! $CRTN.foo" )
Variant Creation Model: callGetter(getElement(getElement(getVariable("STREAM"),"stdout"),"writelines"),concatString(getVariable("0<"),") Hello, world! ",getElement(getVariable("CRTN"),"foo")))
Call stack:
#00: $CRTN.foo
Variant Creation Model: getElement(getVariable("CRTN"),"foo")
#01: "$0<) Hello, world! $CRTN.foo"
Variant Creation Model: concatString(getVariable("0<"),") Hello, world! ",getElement(getVariable("CRTN"),"foo"))
#02: $STREAM.stdout.writelines( "$0<) Hello, world! $CRTN.foo" )
Variant Creation Model: callGetter(getElement(getElement(getVariable("STREAM"),"stdout"),"writelines"),concatString(getVariable("0<"),") Hello, world! ",getElement(getVariable("CRTN"),"foo")))
CONTEXT VARIABLES:
< 0
@ null
! {}
: null
= null
% 0UL
^ null
#01: <hvml target="void">
ATTRIBUTES:
target: "void"
CONTENT: undefined
CONTEXT VARIABLES:
< null
@ null
! {}
: null
= null
% 0UL
^ null
Run multiple HVML programs in parallel
PurC can run multiple HVML programs as coroutines in parallel.
For example, we enhance the first HVML program to print Hello, world!
10 times:
<!DOCTYPE hvml>
<hvml target="void">
<iterate on 0 onlyif $L.lt($0<, 10) with $DATA.arith('+', $0<, 1) nosetotail must-yield >
$STREAM.stdout.writelines(
$STR.join($0<, ") Hello, world! --from COROUTINE-", $CRTN.cid))
</iterate>
</hvml>
Assume you named the enhanced version as hello-10.hvml
,
we can run the program as two coroutines in parallel by specifying the command line flag -l
:
$ purc -l hello-10.hvml hello-10.hvml
You will see the following output on your terminal:
0) Hello, world! -- from COROUTINE-3
0) Hello, world! -- from COROUTINE-4
1) Hello, world! -- from COROUTINE-3
1) Hello, world! -- from COROUTINE-4
2) Hello, world! -- from COROUTINE-3
2) Hello, world! -- from COROUTINE-4
3) Hello, world! -- from COROUTINE-3
3) Hello, world! -- from COROUTINE-4
4) Hello, world! -- from COROUTINE-3
4) Hello, world! -- from COROUTINE-4
5) Hello, world! -- from COROUTINE-3
5) Hello, world! -- from COROUTINE-4
6) Hello, world! -- from COROUTINE-3
6) Hello, world! -- from COROUTINE-4
7) Hello, world! -- from COROUTINE-3
7) Hello, world! -- from COROUTINE-4
8) Hello, world! -- from COROUTINE-3
8) Hello, world! -- from COROUTINE-4
9) Hello, world! -- from COROUTINE-3
9) Hello, world! -- from COROUTINE-4
In the above output, COROUTINE-3
and COROUTINE-4
contain the coroutine identifier assigned by PurC for two running instances of the program.
You see that PurC schedules the running instances to execute alternately, i.e., in the manner of coroutines.
If you do not use the flag -l
in the command line, purc
will run the programs one by one:
$ purc hello-10.hvml hello-10.hvml
0) Hello, world! -- from COROUTINE-3
1) Hello, world! -- from COROUTINE-3
2) Hello, world! -- from COROUTINE-3
3) Hello, world! -- from COROUTINE-3
4) Hello, world! -- from COROUTINE-3
5) Hello, world! -- from COROUTINE-3
6) Hello, world! -- from COROUTINE-3
7) Hello, world! -- from COROUTINE-3
8) Hello, world! -- from COROUTINE-3
9) Hello, world! -- from COROUTINE-3
0) Hello, world! -- from COROUTINE-4
1) Hello, world! -- from COROUTINE-4
2) Hello, world! -- from COROUTINE-4
3) Hello, world! -- from COROUTINE-4
4) Hello, world! -- from COROUTINE-4
5) Hello, world! -- from COROUTINE-4
6) Hello, world! -- from COROUTINE-4
7) Hello, world! -- from COROUTINE-4
8) Hello, world! -- from COROUTINE-4
9) Hello, world! -- from COROUTINE-4
Connecting to an HVML renderer
One of the important differences between HVML and other programming languages is that HVML can generate documents described in markup languages like HTML, not just output data to a file or your terminal.
For your convenience, we have prepared some HVML samples in the directory Source/Samples/hvml
of this repository.
After building PurC, the samples will be copied to the building root directory, under the hvml/
subdirectory,
so that you can change to the building root directory and use purc
to run the samples.
For example:
$ cd <path/to/the/building/directory/>
$ purc hvml/fibonacci-void-temp.hvml
This HVML program will output 18 Fibonacci numbers less than 2000.
There is also another version of this program: hvml/fibonacci-html-temp.hvml
.
It will generate an HTML document listing the Fibonacci numbers.
If you run hvml/fibonacci-html-temp.hvml
program by using purc
without any option,
purc
will use the renderer called HEADLESS
.
This renderer will record the messages sent by PurC to the renderer in a local file,
it is /dev/null
by default on Linux.
Because this HVML program did not use $STREM.stdout
anymore, you will see nothing on your terminal.
But you can use the option --verbose
(or the short option -v
) to show the HTML contents generated by the HVML program in your terminal:
$ purc -v hvml/fibonacci-html-temp.hvml
The command will give you the following output:
purc 0.9.20
Copyright (C) 2022, 2023 FMSoft Technologies.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Executing HVML program from `file:///srv/devel/hvml/purc/build/hvml/fibonacci-html-temp.hvml`...
The main coroutine exited.
>> The document generated:
<html>
<head>
<title>Fibonacci Numbers
</title>
</head>
<body id="theBody">
<h1>Fibonacci Numbers less than 2000
</h1>
<ol>
<li>0
</li>
<li>1
</li>
<li>1
</li>
<li>2
</li>
<li>3
</li>
<li>5
</li>
<li>8
</li>
<li>13
</li>
<li>21
</li>
<li>34
</li>
<li>55
</li>
<li>89
</li>
<li>144
</li>
<li>233
</li>
<li>377
</li>
<li>610
</li>
<li>987
</li>
<li>1597
</li>
</ol>
<p>Totally 18 numbers
</p>
</body>
</html>
>> The executed result:
[ 18, 1597 ]
purc
now contains a built-in renderer called Foil
,
which can show the contents of the target document in your terminal according to CSS properties.
We can use the option --rdr-comm=thread
(-c thread
for short) when running purc
to use the renderer:
$ purc -c thread hvml/fibonacci-html-temp.hvml
Here is the screenshot on macOS:
You can also try other samples which illustrate the features of the Foil renderer:
hvml/foil-layouts.hvml
hvml/foil-progress.hvml
hvml/foil-meter.hvml
Note that in the current version (0.9.20), Foil is not fully functional. Shortly, Foil will provide support for most properties of CSS 2.2 and some properties of CSS Level 3, so that you can get a similar experience to a web browser.
You can also direct purc
to connect to a graphics renderer, for example, xGUI Pro
.
It is an advanced HVML renderer based on WebKit.
Assume that you have installed xGUI Pro on your system,
you can run purc
to show the ultimate HTML contents in a window of xGUI Pro.
Please refer to https://github.com/HVML/xGUI-Pro for detailed instructions to install xGUI Pro.
Assume that you have started xGUI Pro from another terminal, then please run purc
with the following options:
$ purc --rdr-comm=socket hvml/fibonacci-html-temp-rdr.hvml
Note that, in the above command line, we execute a modified version of Fibonacci Numbers: hvml/fibonacci-html-temp-rdr.hvml
.
If you compare these two versions, you will find that there is an observe
element in the modified version:
<observe on $CRTN for "rdrState:pageClosed">
<exit with [$count, $last_two] />
</observe>
If there is no such observe
element, the HVML program will exit immediately after generating the HTML document.
By using the observe
element, the HVML program will wait for the time when the page created by the renderer is closed by the user (that is you).
You will see that the contents in a window of xGUI Pro created by hvml/fibonacci-html-temp-rdr.hvml
:
If you close the window by clicking the close box on the caption bar, the HVML program will exit as normal.
For a complete HVML program that gives a better experience,
you can try to run another sample called hvml/calculator-bc.hvml
, which implements an arbitrary precision calculator:
$ purc -c socket hvml/calculator-bc.hvml
Here is the screenshot of hvml/calculator-bc.hvml
:
Or run hvml/planetary-resonance-lines.hvml
, which shows the Planetary Resonance:
$ purc -c socket hvml/planetary-resonance-lines.hvml
Here is the screenshot of hvml/planetary-resonance-lines.hvml
:
For an amazing HVML program that uses multiple coroutines to sieve the prime numbers,
you can run hvml/prime-number-sieve.hvml
, which visually illustrates the prime number sieve algorithm:
$ purc -c socket hvml/prime-number-sieve.hvml
Here is the screenshot of hvml/prime-number-sieve.hvml
:
For example, to use an external dynamic object defined in a shared library in an HVML program,
you can run hvml/file-manager.hvml
, which illustrates the usage of the external dynamic object $FS
:
$ purc -c socket hvml/file-manager.hvml
Below is the screenshot of hvml/file-manager.hvml
:
Since version 0.9.7, PurC provides support for the Python.
You can now embed Python code in HVML, import Python modules, access the Python variables, or call Python functions directly in your HVML program.
For example, the sample hvml/embed-python-animated-3d-random-walk.hvml
shows some 3D random animated walks, which are generated by calling NumPy, in a window of xGUI Pro:
$ purc -c socket hvml/embed-python-animated-3d-random-walk.hvml
Below is the screenshot of this sample:
Options for purc
You can see the all options supported by purc
when you run purc
with -h
option:
$ purc -h
purc (0.9.20) - a standalone HVML interpreter/debugger based on PurC.
Copyright (C) 2022, 2023 FMSoft Technologies.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Usage: purc [ options ... ] [ file | url ] ... | [ app_desc_json | app_desc_ejson ]
The following options can be supplied to the command:
-a --app=< app_name >
Run with the specified app name (default: `cn.fmsoft.hvml.purc`).
-r --runner=< runner_name >
Run with the specified runner name (default: the md5sum of the URL of first HVML program).
-d --data-fetcher=< local | remote >
The data fetcher; use `local` or `remote`.
- `local`: use the built-in data fetcher, and only `file://` URLs
supported.
- `remote`: use the remote data fetcher to support more URL schemas,
such as `http`, `https`, `ftp` and so on.
-c --rdr-comm=< headless | thread | socket | websocket>
The renderer commnunication method; use `headless` (default), `thread`, or `socket`.
- `headless`: use the built-in headless renderer.
- `thread`: use the built-in thread-based renderer.
- `socket`: use the remote UNIX domain socket-based renderer;
- `websocket`: use the remote websocket-based renderer;
`purc` will connect to the renderer via Unix Socket or WebSocket.
-u --rdr-uri=< renderer_uri >
The renderer uri or shortname:
- For the renderer comm method `headless`,
the default value is `file:///dev/null`.
- For the renderer comm method `thread`,
the default value is the first available one:
`foil` if Foil is enabled, otherwise `seeker`.
- For the renderer comm method `socket`,
the default value is `unix:///var/tmp/purcmc.sock`.
- For the renderer comm method `websocket`,
the default value is `ws://localhost:7702`.
-j --request=< json_file | - >
The JSON file contains the request data which will be passed to
the HVML programs; use `-` if the JSON data will be given through
STDIN stream. (Ctrl+D for end of input after you input the JSON data in a terminal.)
-q --query=< query_string >
Use a URL query string (in RFC 3986) for the request data which will be passed to
the HVML programs; e.g., --query='case=displayBlock&lang=zh'.
-P --pageid
The page identifier for the HVML programs which do not run in parallel.
-L --layout-style
The layout style for the HVML programs which do not run in parallel.
This option is only valid if the page type is `plainwin` or `widget`.
-T --toolkit-style
The toolkit style for the HVML programs which do not run in parallel.
This option is only valid if the page type is `plainwin` or `widget`.
-A --transition-style
The transition style for the HVML programs which do not run in parallel.
This option is only valid if the page type is `plainwin`.
-s --allow-switching-rdr=< true | false >
Allow switching renderer.
-l --parallel
Execute multiple programs in parallel.
-v --verbose
Execute the program(s) with verbose output.
-C --copying
Display detailed copying information and exit.
-V --version
Display version information and exit.
-h --help
This help.
(root only options)
-R --chroot <directory>
Change root to the specified directory
(default is the `/app/<app_name>/`)
-U --setuser <user>
Set user identity to the user specified
(default is the user named <app_name> if it exists).
-G --setgroup <group>
Set group identity to the group specified
(default is the group named <app_name> if it exists>).
Run an HVML app in multiple runners
PurC supports running an app within multiple runners.
Here one runner
is one thread in the purc
process.
For this purpose, you can prepare a JSON file or an eJSON file that defines the app, the workspaces, the runners, and the initial HVML programs to run as coroutines in different runners.
Here is an example:
{
"app": "cn.fmsoft.hvml.sample",
"runners": [
{
"name": "Products",
"renderer": { "comm": "socket", "uri": "unix:///var/tmp/purcmc.sock",
"workspaceName": "default", "workspaceLayout": "cn.fmsoft.hvml.sample/layout.html" },
"coroutines": [
{ "url": "hvml/productlist.hvml", "request": {},
"renderer": { "pageType": "widget", "pageName": "productlist", "pageGroupId": "theProductsArea" }
},
{ "url": "hvml/productinfo.hvml", "request": { "productId": 0 },
"renderer": { "pageType": "widget", "pageName": "productinfo", "pageGroupId": "theProductsArea" }
}
]
},
{
"name": "Customers",
"renderer": { "comm": "socket", "uri": "unix:///var/tmp/purcmc.sock",
"workspaceName": "default", "workspaceLayout": "cn.fmsoft.hvml.sample/layout.html" },
"coroutines": [
{ "url": "hvml/customerlist.hvml", "request": {},
"renderer": { "pageType": "widget", "pageName": "customerlist", "pageGroupId": "theCustomersArea" }
},
{ "url": "hvml/customerlist.hvml", "request": { "customerId": 0 },
"renderer": { "pageType": "widget", "pageName": "customerinfo", "pageGroupId": "theCustomersArea" }
}
]
},
{
"name": "Daemons",
"coroutines": [
{ "url": "hvml/check-customers.hvml", "request": { "interval": 10 } },
{ "url": "hvml/check-products.hvml", "request": { "interval": 30 } }
]
},
]
}
Assume that you prepare all HVML programs and save the above JSON as cn.fmsoft.hvml.sample.json
,
you can run purc
in the following way:
$ purc cn.fmsoft.hvml.sample.json
Note that, when running an app in this way,
you can use the command line options in the eJSON file through the variable $OPTS
prepared by purc
when parsing the eJSON file.
This gives a typical application of parameterized eJSON introduced by PurC.
For example, we can specify the command line options:
$ purc --app=cn.fmsoft.hvml.sample my_app.ejson
Then use the option specified by --app
in my_app.ejson
:
{
"app": "$OPTS.app",
"runners": [
{
"name": "Products",
"renderer": { "comm": "socket", "uri": "unix:///var/tmp/purcmc.sock",
"workspaceName": "default", "workspaceLayout": "$OPTS.app/layout.html" },
"coroutines": [
{ "url": "cn.fmsoft.hvml.sample/productlist.hvml", "request": {},
"renderer": { "pageType": "widget", "pageName": "productlist", "pageGroupId": "theProductsArea" }
},
{ "url": "cn.fmsoft.hvml.sample/productinfo.hvml", "request": { "productId": 0 },
"renderer": { "pageType": "widget", "pageName": "productinfo", "pageGroupId": "theProductsArea" }
},
]
},
]
}
All occurrences of $OPTS.app
in my_app.ejson
will be substituted by cn.fmsoft.hvml.sample
.
More HVML samples
You can find more HVML sample programs in the repository HVML Documents,
under the directory samples/
.
You can use purc
to run a sample resided in the remote HVML Documents repository directly:
$ purc --data-fetcher=remote https://github.com/HVML/hvml-docs/raw/master/samples/fibonacci/fibonacci-6.hvml
If the firewall refused to connect to the URL, use the following URL:
$ purc --data-fetcher=remote https://gitlab.fmsoft.cn/hvml/hvml-docs/-/raw/master/samples/fibonacci/fibonacci-6.hvml
Note that when purc
try to load an HVML program from a remote URL,
it will use the remote data fetcher by default.
Since 0.9.0, PurC Fetcher had been included in this repository, and it will be built along with PurC.
Contributing
We welcome anybody to take part in the development and contribute your effort! There are many ways to contribute to PurC:
- Participate in Q&A in our GitHub Discussions.
- Submit bugs and help us verify fixes as they are checked in.
- Review the source code changes.
- Contribute bug fixes.
- Contribute test programs and/or test cases.
- Contribute samples (HVML samples or C/C++ sample programs to use PurC API).
Current Status
This project was launched in June. 2021, and we opened this repo in July 2022. This is version 0.9.20 of PurC.
The main purpose of PurC is to provide a library for you to write your own HVML interpreter. The current version implements almost all features defined by HVML Specification V1.0, and also implements almost all predefined dynamic variables defined by HVML Predefined Variables V1.0. We plan to release PurC version 1.0 in Dec. 2024.
Except for the HVML interpreter, PurC also provides many fundamental features for general C programs:
- PurC provides the APIs for variant management, here variant is the way HVML manages data.
- PurC provides the APIs for parsing JSON and extended JSON.
- PurC provides the APIs for parsing and evaluating a parameterized Hybrid Evalution Expression (HEE).
- PurC provides the APIs for parsing an HTML document.
- PurC provides the APIs for creating multiple HVML runners.
- PurC provides the APIs for parsing an HVML program and scheduling to run it.
You can use these groups of APIs independently according to your needs.
Source Tree of PurC
PurC implements the parser, the interpreter, and some built-in dynamic variant objects for HVML. It is mainly written in C/C++ language and will provide bindings for Python and other script languages in the future.
The source tree of PurC contains the following modules:
Source/PurC/include/
: The global header files.Source/PurC/include/private
: The internal common header files.Source/PurC/utils/
: Some basic and common utilities.Source/PurC/variant/
: The implementation of variant.Source/PurC/vcm/
: The operations of variant creation model tree.Source/PurC/dvobjs/
: The built-in dynamic variant objects.Source/PurC/ejson/
: The implementation of the eJSON parser. The eJSON parser reads an eJSON and constructs a variant creation model tree.Source/PurC/dom/
: The implementation of the DOM tree.Source/PurC/vdom/
: The implementation of the virtual DOM tree.Source/PurC/html/
: The implementation of the HTML parser. The HTML parser reads an HTML document or document fragments and constructs an eDOM tree.Source/PurC/hvml/
: The implementation of the HVML parser. The HTML parser reads an HVML document and constructs a vDOM tree.Source/PurC/xgml/
: The implementation of the XGML parser (Not implemented so far). The XGML parser reads an XGML document or document fragments and constructs an eDOM tree.Source/PurC/xml/
: The XML parser (Not implemented so far). The XML parser parses an XML document or document fragments and constructs an eDOM tree.Source/PurC/instance/
: The operations of PurC instances and sessions.Source/PurC/fetchers/
: The data fetchers fetch data from various data sources (FILE, HTTP, FTP, and so on).Source/PurC/executors/
: The implementation of internal executors.Source/PurC/interpreter/
: The vDOM interpreter.Source/PurC/pcrdr/
: The management of the connection to the renderer.Source/PurC/ports/
: The ports for different operating systems, such as a POSIX-compliant system or Windows.Source/PurC/bindings/
: The bindings for Python, Lua, and other programming languages.Source/ExtDVObjs/math/
: The implementation of the external dynamic variant object$MATH
.Source/ExtDVObjs/fs/
: The implementation of the external dynamic variant object$FS
and$FILE
.Source/CSSEng/
: The CSS parsing and selecting engine derived from libcss of NetSurf project.Source/DOMRuler/
: The library to lay out and stylize a DOM tree by using CSSEng.Source/RemoteFetcher/
: The library used by the PurC Remote Fetcher.Source/WTF/
: The simplified WTF (Web Template Framework) from WebKit.Source/cmake/
: The cmake modules.Source/ThirdParty/
: The third-party libraries, such asgtest
.Source/test/
: The unit test programs.Source/Samples/api
: Samples for using the API of PurC.Source/Samples/hvml
: HVML sample programs.Source/Executables/
: The executables.Source/Executables/purc
: The standalone HVML interpreter/debugger based on PurC, which is an interactive command line program.Source/Executables/purc-fetcher
: The ultimate executable of PurC Remote Fetcher.Source/Tools/
: The tools or scripts for maintaining this project.Source/Tools/aur
: AUR package packaging scripts.Source/Tools/debian
: DEB package packaging scripts.Documents/
: Some documents for developers.
Note that
- The source code in
Source/WTF
is derived from WebKit, which is licensed under BSD and LGPLv2.1. - The source code in
Source/CSSEng
is derived from LibCSS, LibParserUtils, and LibWapcaplet of NetSurf project. These three libraries are licensed under MIT. - The source code in
Source/RemoteFetcher
is derived from WebKit, which is licensed under BSD and LGPLv2.1. - The HTML parser and DOM operations of PurC are derived from Lexbor, which is licensed under the Apache License, Version 2.0.
TODO List
- The HVML 1.0 features not implemented yet.
- The HVML 1.0 predefined variables not implemented yet.
- More tests or test cases.
- More samples.
- Port PurC to Windows.
For the detailed TODO list, please see TODO List.
Other documents
For the release notes, please refer to Release Notes.
For community conduct, please refer to Code of Conduct.
For the coding convention, please refer to Coding Convention.
Authors and Contributors
- Vincent Wei: The architect.
- XUE Shuming: A key developer, the maintainer of most modules, and PurC Fetcher.
- LIU Xin: A developer, the maintainer of the external dynamic variant object
FILE
. - XU Xiaohong: An early developer, who implemented most features of the variant module and most features of the HVML interperter.
- GENG Yue: An early developer, who implemented some built-in dynamic variant objects.
Copying
PurC
Copyright (C) 2021 ~ 2024 FMSoft Technologies
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this program. If not, see https://www.gnu.org/licenses/.
CSSEng
CSSEng is derived from LibCSS, LibParserUtils, and LibWapcaplet of NetSurf project.
These libraries are all licensed under MIT License.
Copyright 2007 ~ 2020 developers of NetSurf project.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
The new source files developed by FMSoft are licensed under LGPLv3:
Copyright (C) 2021 ~ 2024 FMSoft Technologies
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this program. If not, see https://www.gnu.org/licenses/.
DOMRuler
Copyright (C) 2021 ~ 2024 FMSoft https://www.fmsoft.cn
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General License for more details.
You should have received a copy of the GNU Lesser General License along with this program. If not, see http://www.gnu.org/licenses/.
ExtDVObjs/fs
Copyright (C) 2022 LIU Xin
Copyright (C) 2022 FMSoft Technologies
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this program. If not, see https://www.gnu.org/licenses/.
purc
Copyright (C) 2022, 2024 FMSoft Technologies
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.
purc-fetcher
Copyright (C) 2022, 2024 FMSoft Technologies
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.
Tradmarks
HVML
is a registered tradmark of FMSoft Technologies in China and other contries or regions.
呼噜猫
is a registered tradmark of FMSoft Technologies in China and other contries or regions.
Purring Cat
is a tradmark of FMSoft Technologies in China and other contries or regions.
PurC
is a tradmark of FMSoft Technologies in China and other contries or regions.
xGUI
is a tradmark of FMSoft Technologies in China and other contries or regions.