mirror of
https://onedev.site.tesses.net/crosslang/crosslangextras
synced 2026-02-08 17:15:45 +00:00
Get further on reference
This commit is contained in:
@@ -22,7 +22,7 @@ func Pages.Echo(text)
|
|||||||
pages,
|
pages,
|
||||||
<if(text != null)>
|
<if(text != null)>
|
||||||
<true>
|
<true>
|
||||||
<p>{text}</p>
|
<plink(text)>
|
||||||
</true>
|
</true>
|
||||||
<false>
|
<false>
|
||||||
<p>No text available</p>
|
<p>No text available</p>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ func main(args)
|
|||||||
}
|
}
|
||||||
else if(ctx.Path == "/about")
|
else if(ctx.Path == "/about")
|
||||||
{
|
{
|
||||||
ctx.WithMimeType("text/html").SendText(Pages.Index());
|
ctx.WithMimeType("text/html").SendText(Pages.About());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if(ctx.Path == "/echo")
|
else if(ctx.Path == "/echo")
|
||||||
|
|||||||
@@ -28,8 +28,11 @@ func Console.setSignals(flag)
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
/^ Clear the console ^/
|
||||||
|
func Console.Clear()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/^ Write Text To Standard Output ^/
|
/^ Write Text To Standard Output ^/
|
||||||
func Console.Write(text)
|
func Console.Write(text)
|
||||||
@@ -81,3 +84,18 @@ func Console.getError()
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
/^
|
||||||
|
Returns Width and Weight of terminal in cells as dictionary
|
||||||
|
^/
|
||||||
|
func Console.getSize()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
p: Long 0-100, Double: 0.0-1.0
|
||||||
|
you must call this everytime you want to update progress
|
||||||
|
^/
|
||||||
|
func Console.ProgressBar(p)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
/^
|
||||||
|
Copy Stream to another (but with progress event)
|
||||||
|
^/
|
||||||
|
func Helpers.CopyToProgress(src,dest,progressCB,$precision)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,12 +3,308 @@ func Net.getIPAddresses($ipv6)
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/^
|
||||||
|
Send an email
|
||||||
|
|
||||||
|
dict looks like this from crosslang's point of view
|
||||||
|
{
|
||||||
|
server = {
|
||||||
|
host = "smtp.example.com",
|
||||||
|
tls = true,
|
||||||
|
port = 465 //You can omit this
|
||||||
|
},
|
||||||
|
auth = {
|
||||||
|
username = "from",
|
||||||
|
password = "THEPASSWORD"
|
||||||
|
},
|
||||||
|
domain = "example.com",
|
||||||
|
from = {
|
||||||
|
name = "The name shown in the mail where it is from",
|
||||||
|
email = "from@example.com"
|
||||||
|
},
|
||||||
|
to = "to@example.com",
|
||||||
|
subject = "My little message",
|
||||||
|
body = {
|
||||||
|
type = "text/html",
|
||||||
|
data = "<h1>Hello, world</h1>"
|
||||||
|
},
|
||||||
|
attachments = [
|
||||||
|
{
|
||||||
|
name = "myimg.png",
|
||||||
|
type = "image/png",
|
||||||
|
data = embed("myimg.png")
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
^/
|
||||||
|
func Net.Smtp.Send(dict)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/^ Start server with specified port (and block) server is described by Net.Http.Server ^/
|
/^ Start server with specified port (and block) server is described by Net.Http.Server ^/
|
||||||
func Net.Http.ListenSimpleWithLoop(server, port)
|
func Net.Http.ListenSimpleWithLoop(server, port)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
/^
|
||||||
|
Listen on unused port
|
||||||
|
^/
|
||||||
|
func Net.Http.ListenOnUnusedPort(server)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Create a http server (allows multiple)
|
||||||
|
server schema is Net.Http.Server
|
||||||
|
^/
|
||||||
|
func Net.Http.HttpServer(server,portOrUnixPath, $printIPs)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Create a file server
|
||||||
|
returns schema Net.Http.FileServer
|
||||||
|
^/
|
||||||
|
func Net.Http.FileServer(vfs,allowListing,spa)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Create a server you can mount to, must mount parents before child
|
||||||
|
returns schema Net.Http.MountableServer
|
||||||
|
^/
|
||||||
|
func Net.Http.MountableServer(root)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Download file to string
|
||||||
|
^/
|
||||||
|
func Net.Http.DownloadToString(url)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Download file to stream
|
||||||
|
^/
|
||||||
|
func Net.Http.DownloadToStream(url,strm)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Download file to file
|
||||||
|
^/
|
||||||
|
func Net.Http.DownloadToFile(url,vfs,path)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Create a websocket connection
|
||||||
|
^/
|
||||||
|
func Net.Http.WebSocketClient(url,headers,conn,$successCB)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Convert text like this: "My page is https://tesses.net/\nExample email is mailto:example@example.com" to "My page is <a href=\"https://tesses.net/\"">https:/tesses.net/</a><br>Example email is <a href=\"mailto:example@example.com\">example@example.com</a>"
|
||||||
|
|
||||||
|
for html expressions you can use <plink("Some\nText")> (the string can be dynamic) will become <p>Some<br>Text</p> instead of this function if you want a p tag with the returned value
|
||||||
|
^/
|
||||||
|
func Net.Http.HtmlP(text)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^ Html encode some text (this will be implicit in html expressions) ^/
|
||||||
|
func Net.Http.HtmlEncode(html)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Encode url query params
|
||||||
|
^/
|
||||||
|
func Net.Http.UrlEncode(param)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Decode url query params (this is done implcitly on server ctx.QueryParams)
|
||||||
|
^/
|
||||||
|
func Net.Http.UrlDecode(param)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Encode url path
|
||||||
|
^/
|
||||||
|
func Net.Http.UrlPathEncode(param)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Decode url path
|
||||||
|
^/
|
||||||
|
func Net.Http.UrlDecode(param)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Get mimetype from filename
|
||||||
|
^/
|
||||||
|
func Net.Http.MimeType(filename)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Create stream for request body
|
||||||
|
strm: a stream
|
||||||
|
mimeType: the mimetype
|
||||||
|
^/
|
||||||
|
func Net.Http.StreamHttpRequestBody(strm, mimeType)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Create text for request body
|
||||||
|
text: some text
|
||||||
|
mimeType: the mimetype
|
||||||
|
^/
|
||||||
|
func Net.Http.TextHttpRequestBody(text, mimeType)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Create json for request body
|
||||||
|
json: some json
|
||||||
|
^/
|
||||||
|
func Net.Http.JsonHttpRequestBody(json)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^ The second parameter's schema for Net.Http.MakeRequest ^/
|
||||||
|
class Net.Http.HttpRequestExtra : Dictionary
|
||||||
|
{
|
||||||
|
/^
|
||||||
|
The http method (defaults to GET) its a string
|
||||||
|
^/
|
||||||
|
public Method;
|
||||||
|
|
||||||
|
/^
|
||||||
|
Ignore the ssl errors (defaults to false)
|
||||||
|
^/
|
||||||
|
public IgnoreSSLErrors;
|
||||||
|
|
||||||
|
/^
|
||||||
|
Follow redirects (defaults to false)
|
||||||
|
^/
|
||||||
|
public FollowRedirects;
|
||||||
|
|
||||||
|
/^
|
||||||
|
Trusted certificate string (if it uses self signed certificate)
|
||||||
|
^/
|
||||||
|
public TrustedRootCertBundle;
|
||||||
|
/^
|
||||||
|
List of request headers [{"Key": "User-Agent","Value": "Your User Agent"}]
|
||||||
|
^/
|
||||||
|
public RequestHeaders;
|
||||||
|
/^
|
||||||
|
Body (can be either any of the Net.Http.*HttpRequestBody or a dictionary with the schema Net.Http.DictionaryHttpRequestBody)
|
||||||
|
^/
|
||||||
|
public Body;
|
||||||
|
}
|
||||||
|
public Net.Http.DictionaryHttpRequestBody : Dictionary {
|
||||||
|
/^
|
||||||
|
Handle the headers (so you can add headers), schema is Net.Http.HttpDictionary
|
||||||
|
^/
|
||||||
|
public HandleHeaders(httpdict)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/^
|
||||||
|
Write to the stream
|
||||||
|
^/
|
||||||
|
public Write(strm)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/^ The response of Net.Http.MakeRequest ^/
|
||||||
|
class Net.Http.HttpResponse
|
||||||
|
{
|
||||||
|
/^
|
||||||
|
Copy response to stream
|
||||||
|
^/
|
||||||
|
public CopyToStream(strm)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Read the response as a string
|
||||||
|
^/
|
||||||
|
|
||||||
|
public ReadAsString()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/^
|
||||||
|
Read the response as json
|
||||||
|
^/
|
||||||
|
public ReadAsJson()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Read the response as a stream
|
||||||
|
^/
|
||||||
|
public ReadAsStream()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Get the status code
|
||||||
|
^/
|
||||||
|
public getStatusCode()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/^
|
||||||
|
Get the http version
|
||||||
|
^/
|
||||||
|
public getVersion()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Get the response headers, schema is Net.Http.HttpDictionary
|
||||||
|
^/
|
||||||
|
public getResponseHeaders()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/^
|
||||||
|
url: the url of the request
|
||||||
|
extra: optional (extra parameters for http request schema is: Net.Http.HttpRequestExtra)
|
||||||
|
returns Net.Http.HttpResponse
|
||||||
|
|
||||||
|
extra example
|
||||||
|
{
|
||||||
|
Method = "POST",
|
||||||
|
FollowRedirects = true,
|
||||||
|
RequestHeaders = [
|
||||||
|
{Key = "User-Agent", Value = "curl/7.54.1"}
|
||||||
|
],
|
||||||
|
Body = Net.Http.JsonHttpRequestBody({MyItem = 5})
|
||||||
|
}
|
||||||
|
^/
|
||||||
|
func Net.Http.MakeRequest(url,$extra)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/^ schema from list entries from return value of Net.getIPAddresses ^/
|
/^ schema from list entries from return value of Net.getIPAddresses ^/
|
||||||
class Net.IPAddress {
|
class Net.IPAddress {
|
||||||
@@ -18,7 +314,7 @@ class Net.IPAddress {
|
|||||||
public Address;
|
public Address;
|
||||||
}
|
}
|
||||||
|
|
||||||
/^ schema for server ^/
|
/^ schema for server (dict or class) or can be closure instead (ctx)=>{ return false;} ^/
|
||||||
class Net.Http.Server {
|
class Net.Http.Server {
|
||||||
/^ Handle the request (ctx schema is Net.Http.ServerContext) returns true (handled request) or false (didn't handle request) (any function that accepts a server can also be passed with this directly) ^/
|
/^ Handle the request (ctx schema is Net.Http.ServerContext) returns true (handled request) or false (didn't handle request) (any function that accepts a server can also be passed with this directly) ^/
|
||||||
|
|
||||||
@@ -27,6 +323,113 @@ class Net.Http.Server {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/^ schema for Net.Http.FileServer ^/
|
||||||
|
class Net.Http.FileServer : Net.Http.Server {}
|
||||||
|
/^ schema for Net.Http.MountableServer ^/
|
||||||
|
class Net.Http.MountableServer : Net.Http.Server {
|
||||||
|
/^
|
||||||
|
Add server mount
|
||||||
|
path: a path or string such as /mount (if req is /mount/a svr will see /a )
|
||||||
|
|
||||||
|
^/
|
||||||
|
public Mount(path, svr)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Remove server mount
|
||||||
|
path: same path as when you mounted
|
||||||
|
^/
|
||||||
|
public Unmount(path)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/^ schema for Net.Http.HttpDictionary ^/
|
||||||
|
class Net.Http.HttpDictionary : NativeObject {
|
||||||
|
/^
|
||||||
|
Add a String, Long, Double or DateTime (adds)
|
||||||
|
^/
|
||||||
|
public AddValue(key, value)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Set a String, Long, Double or DateTime (replaces all)
|
||||||
|
^/
|
||||||
|
public SetValue(key, value)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Clears the dictionary (or if key is provided just the key)
|
||||||
|
^/
|
||||||
|
public Clear($key)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Try to get the first boolean (otherwise returns false)
|
||||||
|
^/
|
||||||
|
public GetFirstBoolean(key)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Try to get the first string or return null if there is no values with key
|
||||||
|
^/
|
||||||
|
public TryGetFirst(key)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Does TryGetFirst and checks if it is a Double else returns null
|
||||||
|
^/
|
||||||
|
public TryGetFirstDouble(key)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Does TryGetFirst and checks if it is a Long else returns null
|
||||||
|
^/
|
||||||
|
public TryGetFirstInt(key)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Does TryGetFirst and checks if it is a Date else returns null
|
||||||
|
^/
|
||||||
|
public TryGetFirstDate(key)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Returns a list of all key value pairs {"Key": "","Value": ""}
|
||||||
|
^/
|
||||||
|
public ToList()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Tries to get the Content-Disposition header if not returns null
|
||||||
|
Returns dictionary like this {"Type":"attachment","FileName":"pic.png","FieldName": ""} if it succeeds
|
||||||
|
^/
|
||||||
|
public TryGetContentDisposition()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Set the content-disposition header
|
||||||
|
filename: The filename
|
||||||
|
type: "inline" or "attachment"
|
||||||
|
fieldname: the field (ex in multipart/form-data)
|
||||||
|
^/
|
||||||
|
public SetContentDisposition(filename,type,$fieldname)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
/^ schema for HTTP ServerContext ^/
|
/^ schema for HTTP ServerContext ^/
|
||||||
class Net.Http.ServerContext {
|
class Net.Http.ServerContext {
|
||||||
/^ Is using https (within tessesframework) ^/
|
/^ Is using https (within tessesframework) ^/
|
||||||
@@ -97,7 +500,7 @@ class Net.Http.ServerContext {
|
|||||||
/^
|
/^
|
||||||
Parse multipart/form-data
|
Parse multipart/form-data
|
||||||
pass closure that (mime,filename,name)=>{ return SomeStream; }
|
pass closure that (mime,filename,name)=>{ return SomeStream; }
|
||||||
note: you need to close the streams manually due to how crosslang works
|
or a vfs (the files will be extracted to root (indexed) will return list of {"RealFileName": "/1.bin","FileName": "file.png","Mime": "image/png","Name": "file"}) (Name is the field name)
|
||||||
^/
|
^/
|
||||||
|
|
||||||
public ParseFormData(cb)
|
public ParseFormData(cb)
|
||||||
@@ -147,6 +550,14 @@ class Net.Http.ServerContext {
|
|||||||
public SendBytes(strm)
|
public SendBytes(strm)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Send a redirect to path
|
||||||
|
status_code is optional
|
||||||
|
^/
|
||||||
|
public SendRedirect(path,$status_code)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/^ With mime type (returns the ctx) ^/
|
/^ With mime type (returns the ctx) ^/
|
||||||
@@ -164,6 +575,15 @@ class Net.Http.ServerContext {
|
|||||||
public WithContentDisposition(filename, inline)
|
public WithContentDisposition(filename, inline)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
With a redirect to path
|
||||||
|
status_code is optional
|
||||||
|
returns ctx
|
||||||
|
^/
|
||||||
|
public WithLocationHeader(path,$status_code)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
/^ Add response header (add it if it already exists) (returns the ctx) ^/
|
/^ Add response header (add it if it already exists) (returns the ctx) ^/
|
||||||
public WithHeader(key,value) {
|
public WithHeader(key,value) {
|
||||||
@@ -174,6 +594,43 @@ class Net.Http.ServerContext {
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
/^ Start a websocket session ^/
|
/^
|
||||||
|
Start a websocket session
|
||||||
|
session schema is Net.Http.WebSocketServerSession
|
||||||
|
^/
|
||||||
|
public StartWebSocketSession(session)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Get the path with query params (will have POST params)
|
||||||
|
^/
|
||||||
|
public GetUrlWithQuery()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
|
||||||
|
Get the original path with query params (will have POST params)
|
||||||
|
^/
|
||||||
|
public GetOriginalPathWithQuery()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Get the absolute path
|
||||||
|
^/;
|
||||||
|
public MakeAbsolute(path)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Get the server root
|
||||||
|
^/
|
||||||
|
public GetServerRoot()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
21
Tesses.CrossLang.Reference/src/runtime_methods/path.tcross
Normal file
21
Tesses.CrossLang.Reference/src/runtime_methods/path.tcross
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/^
|
||||||
|
Create a Path from string
|
||||||
|
^/
|
||||||
|
func Path.FromString(path)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Create a Path from parts
|
||||||
|
^/
|
||||||
|
func Path.Create(relative,parts)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Create Absolute Root Path
|
||||||
|
^/
|
||||||
|
func Path.Root()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
129
Tesses.CrossLang.Reference/src/runtime_methods/process.tcross
Normal file
129
Tesses.CrossLang.Reference/src/runtime_methods/process.tcross
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
/^
|
||||||
|
Create a proces object
|
||||||
|
^/
|
||||||
|
class Process : NativeObject {
|
||||||
|
/^
|
||||||
|
The constructor
|
||||||
|
^/
|
||||||
|
public Process()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Must be absolute
|
||||||
|
^/
|
||||||
|
public FileName;
|
||||||
|
/^
|
||||||
|
Redirect stdin
|
||||||
|
^/
|
||||||
|
public RedirectStandardInput;
|
||||||
|
/^
|
||||||
|
Redirect stdout
|
||||||
|
^/
|
||||||
|
public RedirectStandardOutput;
|
||||||
|
/^
|
||||||
|
Redirect stderr
|
||||||
|
^/
|
||||||
|
public RedirectStandardError;
|
||||||
|
/^
|
||||||
|
Set the directory the process will be running in
|
||||||
|
Must be a string
|
||||||
|
^/
|
||||||
|
public WorkingDirectory;
|
||||||
|
/^
|
||||||
|
Inherit parent environment variables
|
||||||
|
^/
|
||||||
|
public InheritParentEnvironment;
|
||||||
|
/^
|
||||||
|
CommandLine Arguments (list of strings not a string)
|
||||||
|
No need to put filename as first arg
|
||||||
|
^/
|
||||||
|
public Arguments;
|
||||||
|
/^
|
||||||
|
List of environment variables
|
||||||
|
{Key="",Value= ""}
|
||||||
|
^/
|
||||||
|
public Environment;
|
||||||
|
/^
|
||||||
|
Returns true if it started, false if not
|
||||||
|
^/
|
||||||
|
public Start()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Wait for process to exit
|
||||||
|
^/
|
||||||
|
public Join()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Wait for process to exit
|
||||||
|
^/
|
||||||
|
public WaitForExit()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Has the process exited
|
||||||
|
^/
|
||||||
|
public getHasExited()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Terminate the process
|
||||||
|
^/
|
||||||
|
public Terminate()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Close the stdin stream
|
||||||
|
^/
|
||||||
|
public CloseStdInNow()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Kill with signal
|
||||||
|
^/
|
||||||
|
public Kill(sig)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Get the stdin stream
|
||||||
|
^/
|
||||||
|
public getStandardInput(){}
|
||||||
|
/^
|
||||||
|
Get the stdout stream
|
||||||
|
^/
|
||||||
|
public getStandardOutput(){}
|
||||||
|
/^
|
||||||
|
Get the stderr stream
|
||||||
|
^/
|
||||||
|
public getStandardError(){}
|
||||||
|
}
|
||||||
|
|
||||||
|
/^
|
||||||
|
example dict
|
||||||
|
{
|
||||||
|
FileName = "git",
|
||||||
|
Arguments = ["clone","https://gitea.site.tesses.net/tesses50/crosslang.git"],
|
||||||
|
Environment = [],
|
||||||
|
InheritParentEnvironment=true,
|
||||||
|
RedirectStandardInput=false,
|
||||||
|
RedirectStandardOutput=false,
|
||||||
|
RedirectStandardError=false,
|
||||||
|
WorkingDirectory="/tmp"
|
||||||
|
}
|
||||||
|
|
||||||
|
returns instance of Process or null if fails
|
||||||
|
^/
|
||||||
|
|
||||||
|
func Process.Start(dict)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
56
Tesses.CrossLang.Reference/src/runtime_methods/sqlite.tcross
Normal file
56
Tesses.CrossLang.Reference/src/runtime_methods/sqlite.tcross
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/^
|
||||||
|
Returns instance of SQLiteDatabase
|
||||||
|
^/
|
||||||
|
func Sqlite.Open(filename)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Escapes a String, Long or Double (everything else returns NULL)
|
||||||
|
^/
|
||||||
|
func Sqlite.Escape(v)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Closes the db
|
||||||
|
^/
|
||||||
|
func Sqlite.Close(db)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Returns a string if an error happens
|
||||||
|
Returns list of dictionaries that the column values are accessed by dictionary keys
|
||||||
|
^/
|
||||||
|
func Sqlite.Exec(db,sql)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Sqlite Database Instance
|
||||||
|
^/
|
||||||
|
class SQLiteDatabase {
|
||||||
|
/^
|
||||||
|
Throws if an error happens
|
||||||
|
Returns list of dictionaries that the column values are accessed by dictionary keys
|
||||||
|
^/
|
||||||
|
public Exec(sql)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Escapes a String, Long or Double (everything else returns NULL)
|
||||||
|
^/
|
||||||
|
public Escape(v)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Closes the database
|
||||||
|
^/
|
||||||
|
public Close()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
145
Tesses.CrossLang.Reference/src/runtime_methods/std.tcross
Normal file
145
Tesses.CrossLang.Reference/src/runtime_methods/std.tcross
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
/^
|
||||||
|
Parse Long from String
|
||||||
|
base: (optional) base of number
|
||||||
|
returns null if it fails
|
||||||
|
^/
|
||||||
|
func ParseLong(str,$base)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Parse Double from String
|
||||||
|
returns null if it fails
|
||||||
|
^/
|
||||||
|
func ParseDouble(str)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Get type of object as String
|
||||||
|
^/
|
||||||
|
func TypeOf(o)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Is object defined
|
||||||
|
^/
|
||||||
|
func TypeIsDefined(o)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Is object heap
|
||||||
|
^/
|
||||||
|
func TypeIsHeap(o)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Is object number
|
||||||
|
^/
|
||||||
|
func TypeIsNumber(o)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Is object long
|
||||||
|
^/
|
||||||
|
func TypeIsLong(o)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Is object double
|
||||||
|
^/
|
||||||
|
func TypeIsDouble(o)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Is object string
|
||||||
|
^/
|
||||||
|
func TypeIsString(o)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Is object callable
|
||||||
|
^/
|
||||||
|
func TypeIsCallable(o)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Is object a class
|
||||||
|
^/
|
||||||
|
func TypeIsClass(o)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Is object a dictionary
|
||||||
|
^/
|
||||||
|
func TypeIsDictionary(o)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Is object a list
|
||||||
|
^/
|
||||||
|
func TypeIsList(o)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Is object a stream
|
||||||
|
^/
|
||||||
|
func TypeIsStream(o)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Is object a vfs
|
||||||
|
^/
|
||||||
|
func TypeIsVFS(o)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Is object a datetime
|
||||||
|
^/
|
||||||
|
func TypeIsDateTime(o)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Parse version from string,
|
||||||
|
if TypeIsVersion(textOrVersion) return textOrVersion
|
||||||
|
^/
|
||||||
|
func Version.Parse(textOrVersion)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Create version from ByteArray
|
||||||
|
^/
|
||||||
|
func Version.FromByteArray(ba, offset)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Create version from long
|
||||||
|
^/
|
||||||
|
func Version.FromLong(num)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/^
|
||||||
|
Load a native plugin, requires a dynamic linker and shared build of libcrosslang
|
||||||
|
^/
|
||||||
|
func Reflection.LoadNativePlugin(path)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
169
Tesses.CrossLang.Reference/src/runtime_methods/vm.tcross
Normal file
169
Tesses.CrossLang.Reference/src/runtime_methods/vm.tcross
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
/^
|
||||||
|
Get root environment as a dictionary
|
||||||
|
^/
|
||||||
|
func VM.getRootEnvironmentAsDictionary()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Get root environment, for reflection purposes
|
||||||
|
^/
|
||||||
|
func VM.getRootEnvironment()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Get current environment, for reflection purposes
|
||||||
|
^/
|
||||||
|
func VM.getCurrentEnvironment()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Create root environment
|
||||||
|
^/
|
||||||
|
func VM.CreateEnvironment($dict)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Load a crossvm executable
|
||||||
|
^/
|
||||||
|
func VM.LoadExecutable(strm)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Eval source code
|
||||||
|
^/
|
||||||
|
func VM.Eval(source)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Compile source code (dict schema is VM.CompileDictionary)
|
||||||
|
Returns {Success=true} if it succeeds or {Success=false, Reason="Reason String"} if it fails
|
||||||
|
^/
|
||||||
|
func VM.Compile(dict)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Get the ast of a program
|
||||||
|
^/
|
||||||
|
func VM.SourceToAst(source)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Get the runtime version
|
||||||
|
^/
|
||||||
|
func VM.getRuntimeVersion()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Is the program still running
|
||||||
|
^/
|
||||||
|
func VM.getIsRunning()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Run an itteration of the event loop
|
||||||
|
^/
|
||||||
|
func VM.RunEventLoopItteration()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Run the event loop
|
||||||
|
^/
|
||||||
|
func VM.RunEventLoop()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Merge all crvm files into one and returns path inside destVFS of output
|
||||||
|
You should have srcFS a SubdirFilesystem to directory with executable
|
||||||
|
so if the source executable was /app/bin/app-1.0.0.0-prod.crvm you should pass a SubdirFilesystem pointing to the directory /app/bin and sourcePath set to /app-1.0.0.0-prod.crvm and destVFS to a empty SubdirFilesystem
|
||||||
|
^/
|
||||||
|
func VM.Merge(srcVFS,sourcePath,destVFS)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Disassemble crvm file
|
||||||
|
^/
|
||||||
|
func VM.Disassemble(strm,vfs,$generateJSON,$extractResources)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Assemble crvm file
|
||||||
|
^/
|
||||||
|
func VM.Assemble(vfs)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^
|
||||||
|
Schema for VM.Compile dict
|
||||||
|
^/
|
||||||
|
class VM.CompileDictionary : dictionary
|
||||||
|
{
|
||||||
|
/^
|
||||||
|
Name (defaults to out)
|
||||||
|
^/
|
||||||
|
public Name;
|
||||||
|
/^
|
||||||
|
Version like 1.0.0.0-prod
|
||||||
|
^/
|
||||||
|
public Version;
|
||||||
|
/^
|
||||||
|
List of dictionaries that look like this
|
||||||
|
{
|
||||||
|
Source = "func main(args){Console.WriteLine(42);}",
|
||||||
|
FileName = "/home/mike/Documents/Code/app/main.tcross"
|
||||||
|
}
|
||||||
|
^/
|
||||||
|
public Sources;
|
||||||
|
|
||||||
|
/^
|
||||||
|
List of dictionaries that look like this
|
||||||
|
{
|
||||||
|
Name = "Tesses.CrossLang.Args",
|
||||||
|
Version = "1.0.0.0-prod"
|
||||||
|
}
|
||||||
|
^/
|
||||||
|
public Dependencies;
|
||||||
|
/^
|
||||||
|
Compile Tools we were built with
|
||||||
|
List of dictionaries that look like this
|
||||||
|
{
|
||||||
|
Name = "SomePackage",
|
||||||
|
Version = "1.0.0.0-prod"
|
||||||
|
}
|
||||||
|
^/
|
||||||
|
public Tools;
|
||||||
|
/^
|
||||||
|
cross.json info section as a string
|
||||||
|
^/
|
||||||
|
public Info;
|
||||||
|
/^
|
||||||
|
Icon filename (relative to root in ResourceFileSystem)
|
||||||
|
^/
|
||||||
|
public Icon;
|
||||||
|
/^
|
||||||
|
comptime's RootEnvironment
|
||||||
|
^/
|
||||||
|
public CompTime;
|
||||||
|
/^
|
||||||
|
Filesystem that embed and Icon looks in
|
||||||
|
^/
|
||||||
|
public ResourceFileSystem;
|
||||||
|
/^
|
||||||
|
Output stream
|
||||||
|
^/
|
||||||
|
public Output;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -46,6 +46,11 @@ class Stream : HeapObject {
|
|||||||
public CopyTo(stream,$bufferSize)
|
public CopyTo(stream,$bufferSize)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/^ Copy to another stream and limit ^/
|
||||||
|
public CopyToLimit(stream,count,$bufferSize)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
/^
|
/^
|
||||||
Seek to position
|
Seek to position
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ func Tesses.CrossLang.Shell.Docs(dd)
|
|||||||
|
|
||||||
var funcs=false;
|
var funcs=false;
|
||||||
var classes=false;
|
var classes=false;
|
||||||
|
var markdown=false;
|
||||||
|
|
||||||
var funcs_list=[];
|
var funcs_list=[];
|
||||||
var classes_list=[];
|
var classes_list=[];
|
||||||
@@ -29,46 +30,99 @@ func Tesses.CrossLang.Shell.Docs(dd)
|
|||||||
|
|
||||||
func printClasses()
|
func printClasses()
|
||||||
{
|
{
|
||||||
|
if(markdown)
|
||||||
|
Console.WriteLine("## Classes");
|
||||||
|
else
|
||||||
Console.WriteLine("Classes:");
|
Console.WriteLine("Classes:");
|
||||||
each(var cls : classes_list)
|
each(var cls : classes_list)
|
||||||
{
|
{
|
||||||
Console.WriteLine();
|
if(markdown)
|
||||||
Console.WriteLine($"\e[38;5;34m/^{cls.Docs}^/");
|
|
||||||
Console.Write($"\e[38;5;39mclass \e[38;5;42m{cls.Name} ");
|
|
||||||
if(cls.Inherits == "ClassObject")
|
|
||||||
{
|
{
|
||||||
Console.WriteLine("\e[38;5;15m{");
|
Console.WriteLine();
|
||||||
|
Console.WriteLine("```csharp");
|
||||||
|
Console.WriteLine($"/^{cls.Docs}^/");
|
||||||
|
Console.Write($"class {cls.Name} ");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Console.WriteLine($"\e[38;5;15m: \e[38;5;42m{cls.Inherits} \e[38;5;15m{{");
|
Console.WriteLine();
|
||||||
|
Console.WriteLine($"\e[38;5;34m/^{cls.Docs}^/");
|
||||||
|
Console.Write($"\e[38;5;39mclass \e[38;5;42m{cls.Name} ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cls.Inherits == "ClassObject")
|
||||||
|
{
|
||||||
|
if(markdown)
|
||||||
|
Console.WriteLine("{");
|
||||||
|
else
|
||||||
|
Console.WriteLine("\e[38;5;15m{");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(markdown)
|
||||||
|
Console.WriteLine($": {cls.Inherits} {");
|
||||||
|
else
|
||||||
|
Console.WriteLine($"\e[38;5;15m: \e[38;5;42m{cls.Inherits} \e[38;5;15m{{");
|
||||||
|
|
||||||
}
|
}
|
||||||
each(var ent : cls.Entries)
|
each(var ent : cls.Entries)
|
||||||
{
|
{
|
||||||
Console.WriteLine();
|
if(markdown)
|
||||||
Console.WriteLine($"\t\e[38;5;34m/^{ent.Docs}^/");
|
{
|
||||||
Console.Write($"\t\e[38;5;39m{ent.Modifiers} ");
|
Console.WriteLine();
|
||||||
|
Console.WriteLine($"\t/^{ent.Docs}^/");
|
||||||
|
Console.Write($"\t{ent.Modifiers} ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine($"\t\e[38;5;34m/^{ent.Docs}^/");
|
||||||
|
Console.Write($"\t\e[38;5;39m{ent.Modifiers} ");
|
||||||
|
}
|
||||||
if(ent.IsFunction)
|
if(ent.IsFunction)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"\e[38;5;229m{ent.Name}\e[38;5;63m(\e[38;5;15m{ent.Args}\e[38;5;63m)\e[0m");
|
if(markdown)
|
||||||
|
Console.WriteLine($"{ent.Name}({ent.Args})");
|
||||||
|
else
|
||||||
|
Console.WriteLine($"\e[38;5;229m{ent.Name}\e[38;5;63m(\e[38;5;15m{ent.Args}\e[38;5;63m)\e[0m");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Console.WriteLine($"\e[38;5;159m{ent.Name}\e[0m;");
|
if(markdown)
|
||||||
|
Console.WriteLine($"{ent.Name};");
|
||||||
|
else
|
||||||
|
Console.WriteLine($"\e[38;5;159m{ent.Name}\e[0m;");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(markdown)
|
||||||
Console.WriteLine("\e[38;5;15m}\e[0m");
|
{
|
||||||
|
Console.WriteLine("}");
|
||||||
|
Console.WriteLine("```");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Console.WriteLine("\e[38;5;15m}\e[0m");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func printFunctions()
|
func printFunctions()
|
||||||
{
|
{
|
||||||
Console.WriteLine("Functions:");
|
if(markdown)
|
||||||
|
Console.WriteLine("## Functions");
|
||||||
|
else
|
||||||
|
Console.WriteLine("Functions:");
|
||||||
each(var fn : funcs_list)
|
each(var fn : funcs_list)
|
||||||
{
|
{
|
||||||
Console.WriteLine();
|
if(markdown)
|
||||||
Console.WriteLine($"\e[38;5;34m/^{fn.Docs}^/");
|
{
|
||||||
Console.WriteLine($"\e[38;5;39mfunc \e[38;5;229m{fn.Name}\e[38;5;63m(\e[38;5;15m{fn.Args}\e[38;5;63m)\e[0m");
|
Console.WriteLine();
|
||||||
|
Console.WriteLine("```go");
|
||||||
|
Console.WriteLine($"/^{fn.Docs}^/");
|
||||||
|
Console.WriteLine($"func {fn.Name}({fn.Args})");
|
||||||
|
Console.WriteLine("```");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine($"\e[38;5;34m/^{fn.Docs}^/");
|
||||||
|
Console.WriteLine($"\e[38;5;39mfunc \e[38;5;229m{fn.Name}\e[38;5;63m(\e[38;5;15m{fn.Args}\e[38;5;63m)\e[0m");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +215,11 @@ func Tesses.CrossLang.Shell.Docs(dd)
|
|||||||
Console.WriteLine("reference-path: print runtime reference file path");
|
Console.WriteLine("reference-path: print runtime reference file path");
|
||||||
Console.WriteLine("update-reference: update runtime reference");
|
Console.WriteLine("update-reference: update runtime reference");
|
||||||
Console.WriteLine("example: print an example");
|
Console.WriteLine("example: print an example");
|
||||||
|
Console.WriteLine("markdown: print as markdown");
|
||||||
return 0;
|
return 0;
|
||||||
|
case "markdown":
|
||||||
|
markdown=true;
|
||||||
|
break;
|
||||||
case "functions":
|
case "functions":
|
||||||
funcs=true;
|
funcs=true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user