mirror of
https://github.com/wezm/wezm.net.git
synced 2024-12-18 10:19:54 +00:00
Compare commits
4 commits
c5f5be6abe
...
7b2f7dfeb8
Author | SHA1 | Date | |
---|---|---|---|
7b2f7dfeb8 | |||
1dc3ede6be | |||
7b24b7d3c2 | |||
c191d6efd9 |
6 changed files with 135 additions and 20 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "v2/syntaxes/gleam"]
|
||||||
|
path = v2/syntaxes/gleam
|
||||||
|
url = https://github.com/digitalcora/sublime-text-gleam.git
|
|
@ -19,6 +19,7 @@ build_search_index = false
|
||||||
# Theme can be customised by setting the `highlight_theme` variable to a theme supported by Zola
|
# Theme can be customised by setting the `highlight_theme` variable to a theme supported by Zola
|
||||||
highlight_code = true
|
highlight_code = true
|
||||||
smart_punctuation = true
|
smart_punctuation = true
|
||||||
|
extra_syntaxes_and_themes = ["syntaxes/gleam"]
|
||||||
|
|
||||||
[extra]
|
[extra]
|
||||||
author = "Wesley Moore"
|
author = "Wesley Moore"
|
||||||
|
|
|
@ -408,7 +408,7 @@ Enter `systemd-sysusers`. Now the `chrony` package includes a file
|
||||||
`sysusers.conf`, which is installed into `/usr/lib/sysusers.d/chrony.conf` when the package
|
`sysusers.conf`, which is installed into `/usr/lib/sysusers.d/chrony.conf` when the package
|
||||||
is installed:
|
is installed:
|
||||||
|
|
||||||
```tcl
|
```
|
||||||
# Create chrony system user
|
# Create chrony system user
|
||||||
|
|
||||||
u _chrony - "chrony user" /var/lib/chrony /usr/bin/nologin
|
u _chrony - "chrony user" /var/lib/chrony /usr/bin/nologin
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
title = "Building a Hybrid Native Application With Gleam and Tauri"
|
title = "Building a Hybrid Native Application With Gleam and Tauri"
|
||||||
date = 2024-02-19T09:56:49+10:00
|
date = 2024-02-19T09:56:49+10:00
|
||||||
|
|
||||||
#[extra]
|
[extra]
|
||||||
#updated = 2023-01-11T21:11:28+10:00
|
updated = 2024-02-20T22:57:15+10:00
|
||||||
+++
|
+++
|
||||||
|
|
||||||
I took a few hours this weekend to experiment with building a hybrid
|
I took a few hours this weekend to experiment with building a hybrid
|
||||||
|
@ -35,14 +35,50 @@ maintained Elm without the restrictions on interop with existing JavaScript
|
||||||
code.
|
code.
|
||||||
|
|
||||||
To get started here's some Gleam code that demonstrates a decent chunk of the
|
To get started here's some Gleam code that demonstrates a decent chunk of the
|
||||||
language. My blog doesn't highlight Gleam code at the moment so what's shown
|
language:
|
||||||
below is a picture. See [example.gleam](example.gleam) for the source file:
|
|
||||||
|
|
||||||
<img src="gleam-example.png" width="378" alt="">
|
```gleam
|
||||||
|
import gleam/io
|
||||||
|
import gleam/list
|
||||||
|
import gleam/int
|
||||||
|
|
||||||
|
pub type Temperature {
|
||||||
|
F(Float)
|
||||||
|
C(Float)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Celsius {
|
||||||
|
Celsius(Float)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let temps = [C(22.0), C(-5.0), F(0.0), C(0.0), F(32.0)]
|
||||||
|
io.debug(avg(temps))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn avg(measurements: List(Temperature)) -> Celsius {
|
||||||
|
let sum =
|
||||||
|
list.fold(measurements, 0.0, fn(sum, val) {
|
||||||
|
let Celsius(c) = to_c(val)
|
||||||
|
sum +. c
|
||||||
|
})
|
||||||
|
let length =
|
||||||
|
list.length(measurements)
|
||||||
|
|> int.to_float
|
||||||
|
Celsius(sum /. length)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_c(temp: Temperature) -> Celsius {
|
||||||
|
case temp {
|
||||||
|
C(c) -> Celsius(c)
|
||||||
|
F(f) -> Celsius({ f -. 32.0 } /. 1.8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
When run it outputs:
|
When run it outputs:
|
||||||
|
|
||||||
Celcius(1.8444444444444443)
|
Celsius(1.8444444444444443)
|
||||||
|
|
||||||
The generated JavaScript (as of Gleam v1.0.0-rc2) is shown below. While it's
|
The generated JavaScript (as of Gleam v1.0.0-rc2) is shown below. While it's
|
||||||
certainly longer than what you might naively write in JavaScript directly it's
|
certainly longer than what you might naively write in JavaScript directly it's
|
||||||
|
@ -131,7 +167,7 @@ a copy of Chromium in every application, instead relying on the system web view
|
||||||
on the host operating system.
|
on the host operating system.
|
||||||
|
|
||||||
You implement your application logic in Rust and communicate with the UI
|
You implement your application logic in Rust and communicate with the UI
|
||||||
by emitting and listing to events. The end result is a cross-platform desktop
|
by emitting and listening to events. The end result is a cross-platform desktop
|
||||||
app that is a lot smaller than if it were built with Electron.
|
app that is a lot smaller than if it were built with Electron.
|
||||||
|
|
||||||
This weekend I decided to try combining these things to see how feasible it
|
This weekend I decided to try combining these things to see how feasible it
|
||||||
|
@ -171,7 +207,7 @@ fn greet(name: &str) -> String {
|
||||||
|
|
||||||
I then needed to be able to use [the `invoke` function][invoke] from the
|
I then needed to be able to use [the `invoke` function][invoke] from the
|
||||||
[@tauri-apps/api npm package][tauri-apps/api]. Following the pattern I observed
|
[@tauri-apps/api npm package][tauri-apps/api]. Following the pattern I observed
|
||||||
in other Gleam packages. I created a JavaScript file to act as a bridge between
|
in other Gleam packages I created a JavaScript file to act as a bridge between
|
||||||
Gleam and `@tauri-apps/api`:
|
Gleam and `@tauri-apps/api`:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
@ -198,12 +234,12 @@ I could then define the external function in the Gleam code and call it:
|
||||||
pub fn greet(name: String) -> Promise(Result(String, String))
|
pub fn greet(name: String) -> Promise(Result(String, String))
|
||||||
```
|
```
|
||||||
|
|
||||||
The challenge was `greet` is an async function, so it returns a promise, which
|
The next challenge was `greet` is an async function, so it returns a promise,
|
||||||
does not integrate into a [lustre.simple] application well. Fortunately there
|
which does not integrate into a [lustre.simple] application well. Fortunately
|
||||||
the less simple [lustre.application] that adds effects. After looking at some
|
there is the less simple [lustre.application] that adds effects. After looking
|
||||||
existing code I was finally about to come up with a working solution. The full
|
at some existing code I was finally able to come up with a working solution.
|
||||||
Gleam code is shown below. `get_greeting` and `do_get_greeting` being the main
|
The full Gleam code is shown below. `get_greeting` and `do_get_greeting` being
|
||||||
parts of interest.
|
the main parts of interest.
|
||||||
|
|
||||||
```gleam
|
```gleam
|
||||||
// src/demo.gleam
|
// src/demo.gleam
|
||||||
|
@ -305,13 +341,13 @@ fn view(model: Model) -> Element(Msg) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
I added a `Greet` message for when the "Greet" button is clicked. In the `update`
|
I added a `Greet` message for when the "Greet" button is clicked. The `update`
|
||||||
function that doesn't update the model but calls `get_greeting` as its
|
function that doesn't update the model but calls `get_greeting` as its
|
||||||
side-effect. That builds an `Effect` from `do_get_greeting`, which calls the
|
side-effect. That builds an `Effect` from `do_get_greeting`, which calls the
|
||||||
FFI function and maps the `Result` to a `GotGreeting` message containing the
|
FFI function and maps the `Result` to a `GotGreeting` message containing the
|
||||||
greeting or an error message.
|
greeting or an error message.
|
||||||
|
|
||||||
`update` then handles the `GotGreeting` message by updating the model, which in
|
`update` handles the `GotGreeting` message by updating the model, which in
|
||||||
turn updates the UI. I'm skipping over the `Model`, `view`, `update`
|
turn updates the UI. I'm skipping over the `Model`, `view`, `update`
|
||||||
architecture of this Lustre application since it's basically the [Elm
|
architecture of this Lustre application since it's basically the [Elm
|
||||||
architecture]. A similar pattern is seen in Reason React, ReScript, and [React
|
architecture]. A similar pattern is seen in Reason React, ReScript, and [React
|
||||||
|
@ -361,7 +397,7 @@ fn main() {
|
||||||
|
|
||||||
In a production application you'd want a mechanism for cleanly shutting the
|
In a production application you'd want a mechanism for cleanly shutting the
|
||||||
thread down but for experimentation purposes I skipped that. Now I needed to
|
thread down but for experimentation purposes I skipped that. Now I needed to
|
||||||
listen for the `tick` event on the UI. I added another glue function to the FFI
|
listen for the `tick` event in the UI. I added another glue function to the FFI
|
||||||
file:
|
file:
|
||||||
|
|
||||||
```gleam
|
```gleam
|
||||||
|
@ -588,8 +624,8 @@ Some unanswered questions I have from this experiment are:
|
||||||
2. What is the right way to import `gleam.mjs` from JavaScript code?
|
2. What is the right way to import `gleam.mjs` from JavaScript code?
|
||||||
3. What is the structure of the Gleam `build` directory?
|
3. What is the structure of the Gleam `build` directory?
|
||||||
* I see `dev` and `prod` sub-directories.
|
* I see `dev` and `prod` sub-directories.
|
||||||
* Is the `prod` on used when targeting JavaScript (I can't see any
|
* Is the `prod` on used when targeting JavaScript
|
||||||
equivalent of Cargo's `--release` in the `gleam` CLI help).
|
* I can't see any equivalent of Cargo's `--release` in the `gleam` CLI help.
|
||||||
|
|
||||||
The full project code is available here:
|
The full project code is available here:
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,80 @@ pre {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #fcfcfc;
|
color: #fcfcfc;
|
||||||
max-height: 800px;
|
max-height: 800px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.language-asm::after,
|
||||||
|
.language-bash::after,
|
||||||
|
.language-c::after,
|
||||||
|
.language-css::after,
|
||||||
|
.language-dockerfile::after,
|
||||||
|
.language-gleam::after,
|
||||||
|
.language-ini::after,
|
||||||
|
.language-javascript::after,
|
||||||
|
.language-json::after,
|
||||||
|
.language-rust::after,
|
||||||
|
.language-sh::after,
|
||||||
|
.language-tcl::after,
|
||||||
|
.language-toml::after,
|
||||||
|
.language-vim::after,
|
||||||
|
.language-xml::after,
|
||||||
|
.language-yaml::after
|
||||||
|
{
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
right: 0px;
|
||||||
|
color: black;
|
||||||
|
background-color: #FFFA;
|
||||||
|
padding: 0 0.5em 1px 0.5em;
|
||||||
|
border-bottom-left-radius: 8px;
|
||||||
|
}
|
||||||
|
.language-asm::after {
|
||||||
|
content: 'Assembly';
|
||||||
|
}
|
||||||
|
.language-bash::after {
|
||||||
|
content: 'Bash';
|
||||||
|
}
|
||||||
|
.language-c::after {
|
||||||
|
content: 'C';
|
||||||
|
}
|
||||||
|
.language-css::after {
|
||||||
|
content: 'CSS';
|
||||||
|
}
|
||||||
|
.language-dockerfile::after {
|
||||||
|
content: 'Dockerfile';
|
||||||
|
}
|
||||||
|
.language-gleam::after {
|
||||||
|
content: 'Gleam';
|
||||||
|
}
|
||||||
|
.language-ini::after {
|
||||||
|
content: 'INI';
|
||||||
|
}
|
||||||
|
.language-javascript::after {
|
||||||
|
content: 'JavaScript';
|
||||||
|
}
|
||||||
|
.language-json::after {
|
||||||
|
content: 'JSON';
|
||||||
|
}
|
||||||
|
.language-rust::after {
|
||||||
|
content: 'Rust';
|
||||||
|
}
|
||||||
|
.language-sh::after {
|
||||||
|
content: 'Shell';
|
||||||
|
}
|
||||||
|
.language-tcl::after {
|
||||||
|
content: 'Tcl';
|
||||||
|
}
|
||||||
|
.language-toml::after {
|
||||||
|
content: 'TOML';
|
||||||
|
}
|
||||||
|
.language-vim::after {
|
||||||
|
content: 'Vim';
|
||||||
|
}
|
||||||
|
.language-xml::after {
|
||||||
|
content: 'XML';
|
||||||
|
}
|
||||||
|
.language-yaml::after {
|
||||||
|
content: 'YAML';
|
||||||
}
|
}
|
||||||
h1,h2,h3,h4 {
|
h1,h2,h3,h4 {
|
||||||
font-family: $heading-family;
|
font-family: $heading-family;
|
||||||
|
|
1
v2/syntaxes/gleam
Submodule
1
v2/syntaxes/gleam
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 6c2080bf6039aa4c844086953d5aca49a7cd5ab6
|
Loading…
Reference in a new issue