kweb: a ui for k

there are three design rules:

Programs run online, e.g. from this page or locally to access files on disk. All examples in this document are executable and load in the iframe on the right.

calling js from k

k runs in the browser as a WebAssembly module. It is extended with a js function which creates an anonymous javascript function. Arguments are converted from k to js and back.

With some projections we can write a classic html page in k:

css/style rules could be changed from k like that:

style:js[`x;"function style(x){let s=document.createElement('style');
 s.innerText=x;document.head.appendChild(s);return null}"]
style"*{background-color:black}"

kweb.js defines a show function that enables creating ui elements from k values.

k values are connected to visual elements in div nodes in three different modes depending on the second argument:
  1. show[dst; value ] takes a k value
  2. show[dst;`symbol] references a global variable
  3. show[dst; {expr}] evaluates a k expression, which is given by a niladic lambda

A k value is simply shown in the gui. It cannot be modified.
If the value is referenced by symbol, it may be modified by ui interactions which mirror the modification to the k side.
A k {expression} is evaluated each time the ui is updated. It can be used e.g. to add computed columns to a table.

show[dst;x]

  1. dst is the id of a div element where the ui is placed inside. If it does not exist or is empty, a new element is created and appended to the body. show returns the element id.
  2. x is a k value, reference or expression. The kind of ui element that is build depends on the type of x, the value reference by it or returned by the expression.

The example shows a table stored in the variable t. It can be edited by clicking on the values. Editing is commited with the Enter key. The string value is verified by k if it is valid for the row type. Edited values always keep the original type.

There is also hide`id to hide an element. It adds the hidden class to the containing div element. Use show[`id;`] to display it again.

Computed column: The next example shows two tables. The first is stored in the variable t and shown in the div element a that is created in the first line.
The second table is created by an expression and shown in b.
You can edit the first table and see the second updating.

immediate mode ui

The ui updates every time when there is an interaction between k and html/js.

To save work, updating is restricted by the following:

ui elements that are linked by symbols also store the k value of the variable (increasing it's refcount).
Due to k's immutability rules, it is sufficient to compare the stored k value with the value of the variable to detect modifications.

ui variants

So far show decides how to render a k variable by it's type. But there are cases when this is not enough, e.g. a general list may be rendered as:

Or a table should have further properties such as readonly, different row styles, pageable, ...

Variants can be selected by adding a symbol to show's first argument:

t:+`a`b!(1 2;3 4)
show[`dstid`listbox;t]

`listbox chooses an alternative ui building function. There are:

          k-types   default for  
table     DT        TD
listbox   ISFZLDT   ISFZL          multi selection
select    ISFZL     S              dropdown
tree      D                        expanding
input     Cisfz     isfz
edit      C                        textarea
h1        C                        heading
tty       C                        k console
text                cC             span element(`k@)

Custom ui functions can be added in js with kweb.register(dst,f)

If more parameters should be supplied to a ui element, they are passed in a dict as the first argument to show.

The fields id, class and type are treated specially and define the id and classes of the parent div element as well as the ui type.
Remaining fields are added to the created ui element as js properties.

js callbacks and events

If the first argument to show is a dictionary, keys starting with on… are recognized as events. Their values are k functions that are called when the event is triggered.

As an example we create a dropdown list with months. A table query is updated every time the dropdown changes.

separate html and k

When the application has reached a certain size, it may be beneficial to separate k and html.

The gui can be declared in html and k remains functional/analytical without any ui code.

To do so, use a data attribute in the html tag of the div container:

<div id="ta" data-k-type="listbox" data-k-var="t"></div>
<div id="kv" data-k-val="1 2 3"></div>
<div id="dt" data-k-expr="{+/t}"></div>

This is equivalent to the following code in k:

show[`ta`listbox;`t]
show[`kv;1 2 3]
show[`dt;{+/t}]

sep.html is an example of separated html and k. It calls sep.k in the init function:

kweb.init("sep.k")

sep.k only defines the table t:+`abc`def!(|!10;?10)

An application can also be written in html/js without any of the kweb functionality and call k directly when needed.

map.html is an example application that uses the leaflet library to show a slippery map from tiles.
Tiles are normally served from a tile server for each pair of corner coordinates and zoom level. In this case they are generated from k:

tile:{[x;y;z]c:`c@?128*256    /random floats reinterpreted as bytes
     @[c;3+4*!256*256;_-1]}   /set alpha opaque

The requested coordinates are written on top of each image.
The js part inside a leaflet function looks like that:

var ctx = tile.getContext('2d');
let I=K.CK(K.Kx("tile",K.Ki(x),K.Ki(y),K.Ki(z)))   //get a tile from k
let u = new Uint8ClampedArray(I.buffer);
let d = new ImageData(u,256,256);
ctx.putImageData(d,0,0);                           //draw to canvas background
ctx.font="30px monospace"
ctx.fillText(x+"/"+y+"@"+z,0,30)                   //draw tile coordinates
return tile;

plot

sin.html is a program that identifies parameters from a sine wave. It uses the following k code to update a gui for each change of the input parameters, including a graph of the curves:

a:1.;b:2.;r:.5;
x:.4*!50
R:?-#x

f:{[a;b;r;x](r*R)+(a*sin x)+(b* cos x)}
fit:{[]ab::solve[(sin x;cos x);f[a;b;r;x]]}
fit[]

p:{[]`x`y!(x;(f[a;b;r;x];f[ab 0;ab 1;0;x]))}

The input element for A is declared as a k expr in html. It triggeres the recalculation during the update.

<div id="A" data-k-expr="{fit[];ab 0}"></div>
<div id="B" data-k-expr="{ab 1}"></div>

The plot element is also defined as an expression which returns a dict:

<div id="cnv" class="right" data-k-type="plot" data-k-expr="p" data-width=800 data-height=400>

The plot ui element expects a dict whose keys are axis labels and the values are x and y data.

Plots are interactive: Zoom by drawing a rectangle with the mouse and doubleclick to show coordinates.

plot.js converts a k dict to drawing commands that execute canvas api calls. The conversion is written in k in the default application a.k

draw

Plotting is built upon drawing. The draw commands provide a subset of the canvas api without transformations or scaling:

online application

The website ktye.github.io/kweb/k runs all k examples on this page in the iframe. It also serves as an empty program. If you drop a k file on the page, it will be executed.

The front page ktye.github.io is a larger example that shows an editor, a repl and has a plot canvas. Type plot d into the repl at the bottom to see an example and hide`cnv to hide the canvas.

data i/o

kweb/k is served from github which is a static server.

The program runs isolated inside the browser, including k as a WebAssembly module.
That means that k has no access to data on disk.

Data files can be added to a virtual filesystem, by dropping them into the browser. Then k can access them with it's read mechanism: data:<`filename (in this dialect of k).

Files written by k trigger a download: `filename<"data"

Alternatively kweb can be served from a local http server:

kweb.c

kweb.c is a fileserver that runs locally. It has all necessary files attached to the binary, to run a gui application written in k. You can edit k.exe with a texteditor, jump to the end and change a.html or a.k. Files read by k are served from the binary, or from disk. Files written by k are written to disk.

kweb.exe(92kb) the poor man's electron includes:

kweb.exe:7680(thanks to tcc)
  k.wasm:48610
    k.js:7389
 kweb.js:12315
 plot.js:7589
kweb.css:311
  a.html:4011
     a.k:4099
On Windows, double-click on kweb.exe opens a web browser running the gui application.

examples

word formation debugger compiler

ui reference