--- /dev/null
+Subproject commit 1df16a331e64f15a5095d2e79dbc2dcece461382
}
}
-@route.{.GET, "/"}
-(req: &Req, res: &Res) {
- articles := iter.as_iter(news_articles->get() ?? .[])->take(2)->collect();
- res->render("pages/homepage", &.{ articles = articles });
-}
-
-@route.{.GET, "/ovmwasm"}
-(req: &Req, res: &Res) => res->render("pages/ovmwasm", null);
-
-@route.{.GET, "/docs"}
-(req: &Req, res: &Res) => res->render("pages/docs", null);
-
-@route.{.GET, "/docs/install"}
-(req: &Req, res: &Res) => res->render("pages/docs/install", null);
-
-@route.{.GET, "/docs/setup"}
-(req: &Req, res: &Res) => res->render("pages/docs/env_setup", null);
-
-@route.{.GET, "/docs/getting_started"}
-(req: &Req, res: &Res) => res->render("pages/docs/getting_started", null);
-
-@route.{.GET, "/docs/guides"}
-(req: &Req, res: &Res) => res->render("pages/docs/guides", null);
-
-@route.{.GET, "/docs/guides/http-server"}
-(req: &Req, res: &Res) => res->render("pages/docs/guide_http_server", null);
-
-@route.{.GET, "/docs/guides/raylib"}
-(req: &Req, res: &Res) => res->render("pages/docs/guide_raylib", null);
-
-@route.{.GET, "/docs/packages"}
-(req: &Req, res: &Res) => res->render("pages/docs/package", null);
-
-@route.{.GET, "/docs/packages/list"}
-(req: &Req, res: &Res) {
- res->render("pages/docs/package_list", &.{
- core_packages = core_packages,
- third_party_packages = third_party_packages
- });
-}
-
-@route.{.GET, "/playground"}
-(req: &Req, res: &Res) {
- res->body("text/html", "This has been moved to <a href=\"https://try.onyxlang.io\">try.onyxlang.io</a>.");
- res->status(200);
- res->end();
-}
-
-@route.{.GET, "/community"}
-(req: &Req, res: &Res) => res->render("pages/community", null);
-
-
-@route.{.GET, "/robots.txt"}
-(req: &Req, res: &Res) {
- res->file("./www/static/robots.txt");
- res->status(200);
- res->end();
-}
-
-
-Article :: struct { name, description, path, date: str }
-news_articles: Cached_Resource([] Article);
-
-@route.{.GET, "/news/:article"}
-(req: &Req, res: &Res) {
- article_path := req.url_params["article"] ?? "";
- article := array.first(news_articles->get() ?? .[], [n](n.path == article_path));
- if !article {
- res->render("pages/404", null);
- res->status(404);
- return;
- }
-
- filename := tprintf("www/news-articles/{}.html", article.path);
-
- if os.file_exists(filename) {
- contents := os.get_contents(filename);
- defer delete(&contents);
-
- res->render("pages/news_article", &.{
- article = .{ contents = contents, name = article.name, description = article.description }
- });
-
- } else {
- res->render("pages/404", null);
- res->status(404);
- return;
- }
-}
-
-@route.{.GET, "/news"}
-(req: &Req, res: &Res) {
- articles := news_articles->get() ?? .[];
-
- res->render("pages/news", &.{
- articles = articles
- });
-}
-
-@route.{.GET, "/examples"}
-(req: &Req, res: &Res) {
- exs := examples->get() ?? .[];
-
- res->render("pages/examples", &.{
- examples = exs
- });
-}
-
main :: () {
default_log_level(.Error);
load_library_list();
resource = .{},
max_age = 60 * 60, // 1 hour
- fetch_resource = () -> ? [] Article {
- article_file := os.get_contents("www/news-articles/index.json");
- article_index, json_err := json.decode_with_error(article_file);
- if json_err->has_error() {
- return .{};
- }
-
- articles: [] Article;
- #context_scope {
- context.allocator = alloc.heap_allocator;
- json.as_any(article_index.root, &articles);
- }
- return articles;
- },
-
- release_resource = (articles: &[] Article) {
- delete(articles, allocator=alloc.heap_allocator);
- }
+ fetch_resource = fetch_articles,
+ release_resource = release_articles
};
examples = .{
}
}
-
-Package :: struct {
- url, name, description: str;
-}
-
-Example :: struct {
- name, code, html: str;
-}
-
-#local {
- core_packages: [] Package;
- third_party_packages: [] Package;
-
- examples: Cached_Resource([] Example);
-}
-
-load_library_list :: () {
- os.get_contents("www/packages/core_packages.json")
- |> json.decode_into(&core_packages);
-
- slice.sort(core_packages, (a, b) => string.compare(a.name, b.name));
-
- os.get_contents("www/packages/third_party_packages.json")
- |> json.decode_into(&third_party_packages);
-
- slice.sort(third_party_packages, (a, b) => string.compare(a.name, b.name));
-}
-
-load_examples :: () -> ? [] Example {
- #context_scope {
- context.allocator = alloc.heap_allocator;
-
- examples: [] Example;
-
- os.get_contents("www/examples/index.json")
- |> json.decode_into(&examples);
-
- for &example in examples {
- code_path := os.path_join("www/examples", example.code);
- html_path := os.path_join("www/examples", example.html);
-
- example.code = os.get_contents(code_path);
- example.html = os.get_contents(html_path);
- }
-
- return examples;
- }
-}
-
-delete_examples :: (exs: &[] Example) do #context_scope {
- context.allocator = alloc.heap_allocator;
-
- for &ex in *exs {
- delete(&ex.code);
- delete(&ex.html);
- }
-
- delete(exs);
-}
-
--- /dev/null
+use core.alloc
+use core.string
+use core.encoding.json
+use core.os
+use core.slice
+use core {
+ tprintf
+}
+
+Package :: struct {
+ url, name, description: str;
+}
+
+Example :: struct {
+ title, name, description, author, html: str;
+ tags: [] str;
+}
+
+core_packages: [] Package;
+third_party_packages: [] Package;
+
+examples: Cached_Resource([] Example);
+
+
+
+load_library_list :: () {
+ os.get_contents("www/packages/core_packages.json")
+ |> json.decode_into(&core_packages);
+
+ slice.sort(core_packages, (a, b) => string.compare(a.name, b.name));
+
+ os.get_contents("www/packages/third_party_packages.json")
+ |> json.decode_into(&third_party_packages);
+
+ slice.sort(third_party_packages, (a, b) => string.compare(a.name, b.name));
+}
+
+load_examples :: () -> ? [] Example {
+ #context_scope {
+ context.allocator = alloc.heap_allocator;
+
+ examples: struct { list: [..] Example };
+
+ os.get_contents("www/examples/index.json")
+ |> json.decode_into(&examples);
+
+ for &example in examples.list {
+ code_path := os.path_join("www/examples", tprintf("{}.html", example.name));
+ example.html = os.get_contents(code_path);
+ }
+
+ return examples.list;
+ }
+}
+
+delete_examples :: (exs: &[] Example) do #context_scope {
+ context.allocator = alloc.heap_allocator;
+
+ for &ex in *exs {
+ delete(&ex.html);
+ }
+
+ delete(exs);
+}
+
+
+Article :: struct { name, description, path, date: str }
+news_articles: Cached_Resource([] Article);
+
+fetch_articles :: () -> ? [] Article {
+ article_file := os.get_contents("www/news-articles/index.json");
+ article_index, json_err := json.decode_with_error(article_file);
+ if json_err->has_error() {
+ return .{};
+ }
+
+ articles: [] Article;
+ #context_scope {
+ context.allocator = alloc.heap_allocator;
+ json.as_any(article_index.root, &articles);
+ }
+ return articles;
+}
+
+release_articles :: (articles: &[] Article) {
+ delete(articles, allocator=alloc.heap_allocator);
+}
--- /dev/null
+use core {package, *}
+use runtime
+use otmp
+use http
+use http.server {Req :: Request, Res :: Response, route}
+use core.encoding.json
+
+
+@route.{.GET, "/"}
+(req: &Req, res: &Res) {
+ articles := iter.as_iter(news_articles->get() ?? .[])->take(2)->collect();
+ res->render("pages/homepage", &.{ articles = articles });
+}
+
+@route.{.GET, "/ovmwasm"}
+(req: &Req, res: &Res) => res->render("pages/ovmwasm", null);
+
+@route.{.GET, "/docs"}
+(req: &Req, res: &Res) => res->render("pages/docs", null);
+
+@route.{.GET, "/docs/install"}
+(req: &Req, res: &Res) => res->render("pages/docs/install", null);
+
+@route.{.GET, "/docs/setup"}
+(req: &Req, res: &Res) => res->render("pages/docs/env_setup", null);
+
+@route.{.GET, "/docs/getting_started"}
+(req: &Req, res: &Res) => res->render("pages/docs/getting_started", null);
+
+@route.{.GET, "/docs/guides"}
+(req: &Req, res: &Res) => res->render("pages/docs/guides", null);
+
+@route.{.GET, "/docs/guides/http-server"}
+(req: &Req, res: &Res) => res->render("pages/docs/guide_http_server", null);
+
+@route.{.GET, "/docs/guides/raylib"}
+(req: &Req, res: &Res) => res->render("pages/docs/guide_raylib", null);
+
+@route.{.GET, "/docs/packages"}
+(req: &Req, res: &Res) => res->render("pages/docs/package", null);
+
+@route.{.GET, "/docs/packages/list"}
+(req: &Req, res: &Res) {
+ res->render("pages/docs/package_list", &.{
+ core_packages = core_packages,
+ third_party_packages = third_party_packages
+ });
+}
+
+@route.{.GET, "/playground"}
+(req: &Req, res: &Res) {
+ res->body("text/html", "This has been moved to <a href=\"https://try.onyxlang.io\">try.onyxlang.io</a>.");
+ res->status(200);
+ res->end();
+}
+
+@route.{.GET, "/community"}
+(req: &Req, res: &Res) => res->render("pages/community", null);
+
+
+@route.{.GET, "/robots.txt"}
+(req: &Req, res: &Res) {
+ res->file("./www/static/robots.txt");
+ res->status(200);
+ res->end();
+}
+
+
+
+@route.{.GET, "/news/:article"}
+(req: &Req, res: &Res) {
+ article_path := req.url_params["article"] ?? "";
+ article := array.first(news_articles->get() ?? .[], [n](n.path == article_path));
+ if !article {
+ res->render("pages/404", null);
+ res->status(404);
+ return;
+ }
+
+ filename := tprintf("www/news-articles/{}.html", article.path);
+
+ if os.file_exists(filename) {
+ contents := os.get_contents(filename);
+ defer delete(&contents);
+
+ res->render("pages/news_article", &.{
+ article = .{ contents = contents, name = article.name, description = article.description }
+ });
+
+ } else {
+ res->render("pages/404", null);
+ res->status(404);
+ return;
+ }
+}
+
+@route.{.GET, "/news"}
+(req: &Req, res: &Res) {
+ articles := news_articles->get() ?? .[];
+
+ res->render("pages/news", &.{
+ articles = articles
+ });
+}
+
+@route.{.GET, "/examples"}
+(req: &Req, res: &Res) {
+ exs := examples->get() ?? .[];
+
+ res->render("pages/examples", &.{
+ examples = exs
+ });
+}
+
+@route.{.GET, "/examples/:name"}
+(req: &Req, res: &Res) {
+ exs := examples->get() ?? .[];
+ name := req.url_params["name"] ?? "";
+
+ ex := slice.first(exs, [x](x.name == name));
+
+ res->render("pages/example", &.{
+ ex = ex
+ });
+}
+
+
-<p>
- This example shows three different ways to do the same thing: compute Fibonacci numbers.
-</p>
+<h1 class='title'>Fibonacci Sequence</h1>
+<p class='author'>Brendan Hansen</p>
+<div class='description'>This example shows three different ways to do the same thing: compute Fibonacci numbers.</div>
+<pre class='hljs'><code class='language-onyx'>use core.iter
+use core { printf }
+
+//
+// Way number 1: A simple for-loop
+// This method simply uses a for-loop like you would in C to generate
+// the Fibonacci numbers. No tricks to it.
+//
+fib_for_loop :: (n: i32) -> u64 {
+ a: u64 = 0;
+ b: u64 = 1;
+
+ for 0 .. n {
+ tmp := a;
+ a = b;
+ b = tmp + b;
+ }
+
+ return a;
+}
+
+//
+// Way number 2: Functional folding
+// This way creates an iterator that will yield n integers, thats the
+// iter.counter piped to iter.take(n). Then, for each one of those numbers
+// it steps the state, computing the Fibonacci numbers in the process.
+// The final result is the "a" member of the final state.
+
+FibState :: struct { a, b: u64 }
+
+fib_by_fold :: (n: i32) => {
+ end_state :=
+ // This creates an infinite iterator that simply counts up from 0.
+ iter.counter()
+
+ // This limits only taking the first n values.
+ |> iter.take(n)
+
+ // This performs a "fold" or "reduce" operation.
+ |> iter.fold(
+ // This defines the initial accumulator state.
+ FibState.{ a = 0, b = 1 },
+
+ // This defines the "folding" function. It takes the next value
+ // from the iterator, which we simply ignore because we do not
+ // need it, and the previous value of the accumulator. It then
+ // computes and returns the next value for the accumulator.
+ // iter.fold returns the final value of the accumulator.
+ (_, state) => FibState.{
+ a = state.b,
+ b = state.a + state.b
+ }
+ );
+
+ return end_state.a;
+}
+
+
+//
+// Way number 3: A custom iterator
+// This way produces an iterator that yields consecutive Fibonacci numbers.
+// This is slightly faster than the previous methods because it does not have
+// to redo all the work for every query.
+//
+
+fib_iterator :: (n: i32) =>
+ // This is implemented using a generator, which is a custom iterator
+ // that yields values according to the "next" function defined below.
+ iter.generator(
+ // The initial state of the generator.
+ &.{ a = cast(u64) 0, b = cast(u64) 1, counter = n },
+
+ // The generation function. This takes in a pointer to the state
+ // and must return 2 things: the next value and a boolean of whether
+ // to continue or not.
+ //
+ // Notice that the parameter's type is a polymorphic here; notice the $.
+ // This is because the above structure literal is entirely type infered;
+ // no explicit type was given to it. Therefore, there is no type we can
+ // write here that would be correct. We could make a structure for it,
+ // but in this case it is fine to let the compiler do a little magic.
+ (state: & $Ctx) -> (u64, bool) {
+ if state.counter <= 0 {
+ return 0, false;
+ }
+
+ tmp := state.a;
+ state.a = state.b;
+ state.b = state.b + tmp;
+
+ state.counter -= 1;
+ return tmp, true;
+ }
+ );
+
+
+main :: () {
+ // Print the results from fib_for_loop
+ for i in 0 .. 90 {
+ printf("{}: {}\n", i, fib_for_loop(i));
+ }
+
+ // Print the results from fib_by_fold
+ for i in 0 .. 90 {
+ printf("{}: {}\n", i, fib_by_fold(i));
+ }
+
+ // Print the results from fib_iterator
+ for value, index in fib_iterator(90) {
+ printf("{}: {}\n", index, value);
+ }
+}</code></pre>
+++ /dev/null
-use core.iter
-use core { printf }
-
-//
-// Way number 1: A simple for-loop
-// This method simply uses a for-loop like you would in C to generate
-// the Fibonacci numbers. No tricks to it.
-//
-fib_for_loop :: (n: i32) -> u64 {
- a: u64 = 0;
- b: u64 = 1;
-
- for 0 .. n {
- tmp := a;
- a = b;
- b = tmp + b;
- }
-
- return a;
-}
-
-//
-// Way number 2: Functional folding
-// This way creates an iterator that will yield n integers, thats the
-// iter.counter piped to iter.take(n). Then, for each one of those numbers
-// it steps the state, computing the Fibonacci numbers in the process.
-// The final result is the "a" member of the final state.
-
-FibState :: struct { a, b: u64 }
-
-fib_by_fold :: (n: i32) => {
- end_state :=
- // This creates an infinite iterator that simply counts up from 0.
- iter.counter()
-
- // This limits only taking the first n values.
- |> iter.take(n)
-
- // This performs a "fold" or "reduce" operation.
- |> iter.fold(
- // This defines the initial accumulator state.
- FibState.{ a = 0, b = 1 },
-
- // This defines the "folding" function. It takes the next value
- // from the iterator, which we simply ignore because we do not
- // need it, and the previous value of the accumulator. It then
- // computes and returns the next value for the accumulator.
- // iter.fold returns the final value of the accumulator.
- (_, state) => FibState.{
- a = state.b,
- b = state.a + state.b
- }
- );
-
- return end_state.a;
-}
-
-
-//
-// Way number 3: A custom iterator
-// This way produces an iterator that yields consecutive Fibonacci numbers.
-// This is slightly faster than the previous methods because it does not have
-// to redo all the work for every query.
-//
-
-fib_iterator :: (n: i32) =>
- // This is implemented using a generator, which is a custom iterator
- // that yields values according to the "next" function defined below.
- iter.generator(
- // The initial state of the generator.
- &.{ a = cast(u64) 0, b = cast(u64) 1, counter = n },
-
- // The generation function. This takes in a pointer to the state
- // and must return 2 things: the next value and a boolean of whether
- // to continue or not.
- //
- // Notice that the parameter's type is a polymorphic here; notice the $.
- // This is because the above structure literal is entirely type infered;
- // no explicit type was given to it. Therefore, there is no type we can
- // write here that would be correct. We could make a structure for it,
- // but in this case it is fine to let the compiler do a little magic.
- (state: & $Ctx) -> (u64, bool) {
- if state.counter <= 0 {
- return 0, false;
- }
-
- tmp := state.a;
- state.a = state.b;
- state.b = state.b + tmp;
-
- state.counter -= 1;
- return tmp, true;
- }
- );
-
-
-main :: () {
- // Print the results from fib_for_loop
- for i in 0 .. 90 {
- printf("{}: {}\n", i, fib_for_loop(i));
- }
-
- // Print the results from fib_by_fold
- for i in 0 .. 90 {
- printf("{}: {}\n", i, fib_by_fold(i));
- }
-
- // Print the results from fib_iterator
- for value, index in fib_iterator(90) {
- printf("{}: {}\n", index, value);
- }
-}
-
-<p>
- This example shows various ways of reading and writing to a file.
- The core idea behind files in Onyx is that they extend the <code>io.Stream</code> structure, so you can use the <code>core.io</code> package to interact with them.
-</p>
+<h1 class='title'>File Operations</h1>
+<p class='author'>Brendan Hansen</p>
+<div class='description'>This example shows various ways of reading and writing to a file. The core idea behind files in Onyx is that they extend the <code>io.Stream</code> structure, so you can use the <code>core.io</code> package to interact with them.</div>
+<pre class='hljs'><code class='language-onyx'>use core.os
+use core.io
+use core.string
+use core {
+ printf
+}
+
+#doc "Writes example text into a file."
+write_data_into_file :: (filename: str) {
+ // This is one way of opening a file: call os.open and then os.close later.
+ // os.open returns a Result(os.File, os.FileError), so it must be handled
+ // to use the os.File. This program opts to unwrap the result.
+ file := os.open(filename, .Write)->unwrap();
+ defer os.close(&file);
+
+ // Create an io.Writer over the file stream using io.writer_make.
+ // Also, free it later by defering io.writer_free. This also flushes
+ // the internal buffer of io.Writer to make sure everything is written
+ // to the file.
+ file_writer := io.writer_make(&file);
+ defer io.writer_free(&file_writer);
+
+ // The simplest way of writing a string to the file.
+ io.write(&file_writer, "This is the first line of text.\n");
+
+ // io.write_format can be used to "printf" into a file.
+ // printf can be thought of as io.write_format(&stdio.stream, ...).
+ io.write_format(&file_writer, "This is a {} line of text.\n", "formatted");
+
+ for i in 0 .. 5 {
+ io.write_format(&file_writer, "Another line numbered {}.\n", i);
+ }
+}
+
+#doc "Reads example text from a file."
+read_data_from_file :: (filename: str) {
+ // This is another way of opening a file. Because of the semantics
+ // of `for` loops over Iterators, they can behave like `with`
+ // statements in Python or `using` statements in C#.
+ for file in os.with_file(filename, .Read) {
+ // Create a io.Reader over the file stream.
+ file_reader := io.reader_make(file);
+ defer io.reader_free(&file_reader);
+
+ // Read a single line.
+ first_line := io.read_line(&file_reader);
+ printf("First line: {}\n", first_line);
+
+ // Use io.lines to create an iterator over the remaining
+ // lines in the file.
+ printf("Remaining lines:\n");
+ for line, index in io.lines(&file_reader) {
+ printf("{}: {}\n", index, line);
+ }
+ }
+}
+
+#doc "Reads example text from a file."
+read_whole_file :: (filename: str) {
+ // This is the simplest way to get the entire content of a file
+ // into a string ([] u8). Also, defer "deleting" the string, which
+ // will free the memory allocated for the string.
+ contents := os.get_contents(filename);
+ defer delete(&contents);
+
+ printf("Whole contents:\n{}\n", contents);
+}
+
+main :: () {
+ filename := "test.txt";
+
+ write_data_into_file(filename);
+ read_data_from_file(filename);
+ read_whole_file(filename);
+}</code></pre>
+++ /dev/null
-use core.os
-use core.io
-use core.string
-use core {
- printf
-}
-
-#doc "Writes example text into a file."
-write_data_into_file :: (filename: str) {
- // This is one way of opening a file: call os.open and then os.close later.
- // os.open returns a Result(os.File, os.FileError), so it must be handled
- // to use the os.File. This program opts to unwrap the result.
- file := os.open(filename, .Write)->unwrap();
- defer os.close(&file);
-
- // Create an io.Writer over the file stream using io.writer_make.
- // Also, free it later by defering io.writer_free. This also flushes
- // the internal buffer of io.Writer to make sure everything is written
- // to the file.
- file_writer := io.writer_make(&file);
- defer io.writer_free(&file_writer);
-
- // The simplest way of writing a string to the file.
- io.write(&file_writer, "This is the first line of text.\n");
-
- // io.write_format can be used to "printf" into a file.
- // printf can be thought of as io.write_format(&stdio.stream, ...).
- io.write_format(&file_writer, "This is a {} line of text.\n", "formatted");
-
- for i in 0 .. 5 {
- io.write_format(&file_writer, "Another line numbered {}.\n", i);
- }
-}
-
-#doc "Reads example text from a file."
-read_data_from_file :: (filename: str) {
- // This is another way of opening a file. Because of the semantics
- // of `for` loops over Iterators, they can behave like `with`
- // statements in Python or `using` statements in C#.
- for file in os.with_file(filename, .Read) {
- // Create a io.Reader over the file stream.
- file_reader := io.reader_make(file);
- defer io.reader_free(&file_reader);
-
- // Read a single line.
- first_line := io.read_line(&file_reader);
- printf("First line: {}\n", first_line);
-
- // Use io.lines to create an iterator over the remaining
- // lines in the file.
- printf("Remaining lines:\n");
- for line, index in io.lines(&file_reader) {
- printf("{}: {}\n", index, line);
- }
- }
-}
-
-#doc "Reads example text from a file."
-read_whole_file :: (filename: str) {
- // This is the simplest way to get the entire content of a file
- // into a string ([] u8). Also, defer "deleting" the string, which
- // will free the memory allocated for the string.
- contents := os.get_contents(filename);
- defer delete(&contents);
-
- printf("Whole contents:\n{}\n", contents);
-}
-
-main :: () {
- filename := "test.txt";
-
- write_data_into_file(filename);
- read_data_from_file(filename);
- read_whole_file(filename);
-}
-
-[
- {
- "name": "Reading from standard input",
- "code": "stdin.onyx",
- "html": "stdin.html"
- },
- {
- "name": "Interact with files",
- "code": "files.onyx",
- "html": "files.html"
- },
- {
- "name": "Fibonacci printer",
- "code": "fib.onyx",
- "html": "fib.html"
- }
-]
-
-
+{"by_tag":{"io":["files","stdin"],"reader":["files","stdin"],"os":["files"],"file":["files"],"loops":["fib"],"iterators":["fib"],"input":["stdin"],"conv":["stdin"]},"list":[{"code":"","title":"File Operations","name":"files","tags":["io","reader","os","file"],"author":"Brendan Hansen","description":"This example shows various ways of reading and writing to a file. The core idea behind files in Onyx is that they extend the <code>io.Stream</code> structure, so you can use the <code>core.io</code> package to interact with them."},{"code":"","title":"Fibonacci Sequence","name":"fib","tags":["loops","iterators"],"author":"Brendan Hansen","description":"This example shows three different ways to do the same thing: compute Fibonacci numbers."},{"code":"","title":"Standard Input","name":"stdin","tags":["input","io","reader","conv"],"author":"Brendan Hansen","description":"This example reads a single line of input from <a href=\"https://en.wikipedia.org/wiki/Standard_streams\">standard input</a>, splits it in half on the first space using <a href=\"https://docs.onyxlang.io/packages/core.string.html#bisect\">string.bisect</a>, converts both parts to integers using <a href=\"https://docs.onyxlang.io/packages/core.conv.html#parse\">conv.parse</a>, then prints the results using <a href=\"https://docs.onyxlang.io/packages/core.html#printf\">printf</a> for formatted printing."}]}
\ No newline at end of file
-This example reads a single line of input from <a href="https://en.wikipedia.org/wiki/Standard_streams">standard input</a>, splits it in half on the first space using <a href="https://docs.onyxlang.io/packages/core.string.html#bisect">string.bisect</a>, converts both parts to integers using <a href="https://docs.onyxlang.io/packages/core.conv.html#parse">conv.parse</a>, then prints the results using <a href="https://docs.onyxlang.io/packages/core.html#printf">printf</a> for formatted printing.
+<h1 class='title'>Standard Input</h1>
+<p class='author'>Brendan Hansen</p>
+<div class='description'>This example reads a single line of input from <a href="https://en.wikipedia.org/wiki/Standard_streams">standard input</a>, splits it in half on the first space using <a href="https://docs.onyxlang.io/packages/core.string.html#bisect">string.bisect</a>, converts both parts to integers using <a href="https://docs.onyxlang.io/packages/core.conv.html#parse">conv.parse</a>, then prints the results using <a href="https://docs.onyxlang.io/packages/core.html#printf">printf</a> for formatted printing.</div>
+<pre class='hljs'><code class='language-onyx'>// Use the necessary core libraries
+use core.io
+use core.string
+use core.conv
+
+// Use the printf function that lives in the core package.
+// This cannot be `use core.printf`, because that will look
+// for a package called `printf` in `core`.
+use core {
+ printf
+}
+
+main :: () {
+ // Create a io.Reader over the stdio.stream to be able scan
+ // the input in parts. Also, defer freeing the reader until
+ // the end of `main`.
+ stdin_reader := io.reader_make(&stdio.stream);
+ defer io.reader_free(&stdin_reader);
+
+ // Read a single line of input.
+ line := io.read_line(&stdin_reader);
+
+ // Split the line on the first space.
+ a_str, b_str := string.bisect(line, " ");
+
+ // Parse and convert both parts to i32s, with a default value
+ // of 0 if it fails to parse as an i32.
+ a_value := conv.parse(i32, a_str)->value_or(0);
+ b_value := conv.parse(i32, b_str)->value_or(0);
+
+ // Compute our result.
+ result := a_value + b_value;
+
+ // Output our result using formatted printing.
+ printf("{} + {} = {}\n", a_value, b_value, result);
+}</code></pre>
+++ /dev/null
-// Use the necessary core libraries
-use core.io
-use core.string
-use core.conv
-
-// Use the printf function that lives in the core package.
-// This cannot be `use core.printf`, because that will look
-// for a package called `printf` in `core`.
-use core {
- printf
-}
-
-main :: () {
- // Create a io.Reader over the stdio.stream to be able scan
- // the input in parts. Also, defer freeing the reader until
- // the end of `main`.
- stdin_reader := io.reader_make(&stdio.stream);
- defer io.reader_free(&stdin_reader);
-
- // Read a single line of input.
- line := io.read_line(&stdin_reader);
-
- // Split the line on the first space.
- a_str, b_str := string.bisect(line, " ");
-
- // Parse and convert both parts to i32s, with a default value
- // of 0 if it fails to parse as an i32.
- a_value := conv.parse(i32, a_str)->value_or(0);
- b_value := conv.parse(i32, b_str)->value_or(0);
-
- // Compute our result.
- result := a_value + b_value;
-
- // Output our result using formatted printing.
- printf("{} + {} = {}\n", a_value, b_value, result);
-}
"name": "otmp",
"url": "https://github.com/onyx-lang/pkg-otmp",
"description": "A string templating language, similar to Jinja or Mustache."
+ },
+ {
+ "name": "webgl2",
+ "url": "https://github.com/onyx-lang/pkg-webgl2",
+ "description": "Bindings to WebGL 2. Accessible when targetting JS runtime."
}
]
background: var(--background);
color: var(--text);
- font-family: 'Oxanium', sans-serif;
+ font-family: sans-serif;
}
a {
background-color: var(--primary);
}
+.example-container {
+ margin: 0 auto;
+ max-width: 1200px;
+ display: grid;
+
+ grid-template-columns: 1fr 1fr;
+ gap: 16px;
+}
+
+.example-container > div {
+ padding: 8px;
+}
+
+.example-container > div > div {
+ padding: 8px;
+}
+
+.example-container > div > div > a {
+ border-bottom: none;
+}
+
+.example-container .example-tag {
+ padding: 2px;
+ background-color: var(--primary);
+ border-radius: 4px;
+}
+
+.example > .author { display: none; }
--- /dev/null
+{{ block "title" }}
+Onyx Examples
+{{ endblock }}
+
+{{ let navbar_page = "examples" }}
+
+{{ block "page_content" }}
+
+<div class="container header">
+ <h1>Onyx Examples</h1>
+ <p><a href="/examples">Back to example list</a></p>
+</div>
+
+<div class="container example">
+ {% ex.html %}
+</div>
+
+<div class="container">
+ <div class="title">
+ <h2>Want to learn more?</h2>
+ </div>
+ <p>
+ <a class="link-button" href="/docs">Visit the docs!</a>
+ </p>
+ <p>
+ You can learn more details about Onyx by visiting the docs!
+ There is more examples, a reference manual for the language, and documentation for the standard library.
+ </p>
+</div>
+
+{{ endblock }}
+
+{{ extends "pages/normal_page" }}
+
<p>This page provides several simple examples of Onyx code, showing how to do common things with the standard library.</p>
</div>
-{{ foreach ex in examples }}
-<div class="container">
- <div class="title">
- <h2>{% ex.name %}</h2>
+<div class="example-container">
+ {{ foreach ex in examples }}
+ <div class="container card">
+ <div style="position: relative">
+ <a href="/examples/{% ex.name %}" style="position: absolute; inset: 0">
+ </a>
+
+ <h3>{% ex.title %}</h3>
+
+ <div>
+ {{ foreach tag in ex.tags }}
+ <span class="example-tag">{% tag %}</span>
+ {{ endforeach }}
+ </div>
+
+ <div style="margin: 8px 0;">{% ex.description %}</div>
+ </div>
</div>
-
- <div>
- {% ex.html %}
- </div>
-
- <pre class="hljs"><code class="language-onyx">{% ex.code %}</code></pre>
+ {{ endforeach }}
</div>
-{{ endforeach }}
<div class="container">
<div class="title">