1
0
Fork 0

Compare commits

...

15 Commits

19 changed files with 687 additions and 2 deletions

4
.gitignore vendored
View File

@ -1,3 +1,5 @@
.clj-kondo
.lsp
.calva
.calva
gemini
docs

32
Makefile Normal file
View File

@ -0,0 +1,32 @@
# This makefile builds the website to be published.
# For the HTTP/HTML portion, that's pushed to Github pages.
# For the gemini portion, that's also pushed to my gemini server by this makefile.
source_files := $(shell find content/*.md)
target_files := $(patsubst content/%.md,gemini/%.gmi,$(source_files))
.PHONY: default
default: build-gemini publish-gemini build-html
gemini/%.gmi: content/%.md
lowdown -tgemini $< > $@
gemini/index.gmi: $(source_files)
for file in $(target_files) ; do \
echo "=> $$file" | sed 's/gemini//' >> gemini/index.gmi ; \
done
.PHONY: build-gemini
build-gemini: $(target_files) gemini/index.gmi
cp gemini/_index.gmi gemini/index.gmi
.PHONY: build-html
build-html:
boot publish
.PHONY: clean
clean:
echo ${target_files}
.PHONY: publish
publish-gemini: ${target_files}
rsync -av content/img content/extra gemini/index.gmi $^ gemini.bgenc.net:/var/gemini/

View File

@ -0,0 +1,117 @@
---
title: Solving `app_data` or `ReqData` missing in requests for actix-web
date: 2022-03-26
---
> This post is day 5 of me taking part in the
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
I'm using `actix-web` to set up a web server, and I've been hitting a small
problem that I think other people may come across too.
To explain the problem, let me talk a bit about my setup. I have a custom
middleware that checks if a user is authorized to access a route. It looks like
this:
```rust
impl<S: 'static, B> Service<ServiceRequest> for CheckLoginMiddleware<S>
where
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static,
{
type Response = ServiceResponse<EitherBody<B>>;
type Error = Error;
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
dev::forward_ready!(service);
fn call(&self, req: ServiceRequest) -> Self::Future {
let state = self.state.clone();
let (request, payload) = req.into_parts();
let service = self.service.clone();
let user_token = get_token_from_header(&request);
let path_token = if self.allow_path_tokens {
get_token_from_query(&request)
} else {
None
};
Box::pin(async move {
match verify_auth(state, user_token, path_token, request.path()).await {
Ok(authorized) => {
tracing::debug!("Request authorized, inserting authorization token");
// This is the "important bit" where we insert the authorization token into the request data
request.extensions_mut().insert(authorized);
let service_request =
service.call(ServiceRequest::from_parts(request, payload));
service_request
.await
.map(ServiceResponse::map_into_left_body)
}
Err(err) => {
let response = HttpResponse::Unauthorized().json(err).map_into_right_body();
Ok(ServiceResponse::new(request, response))
}
}
})
}
}
```
The `verify_auth` function is omitted, but the gist of it is that it returns an `Result<Authorized, Error>`.
If the user is authorized, the authorization token `verify_auth` returned is then attached to the request.
Then here's how I use it in a path:
```rust
#[delete("/{store}/{path:.*}")]
async fn delete_storage(
params: web::Path<(String, String)>,
// This parameter is automatically filled with the token
authorized: Option<ReqData<Authorized>>,
) -> Result<HttpResponse, StorageError> {
let (store, path) = params.as_ref();
let mut store_path = get_authorized_path(&authorized, store)?;
store_path.push(path);
if fs::metadata(&store_path).await?.is_file() {
tracing::debug!("Deleting file {:?}", store_path);
fs::remove_file(&store_path).await?;
} else {
tracing::debug!("Deleting folder {:?}", store_path);
fs::remove_dir(&store_path).await?;
}
Ok(HttpResponse::Ok().finish())
}
```
This setup worked for this path, but would absolutely not work for another path.
I inserted logs to track everything, and just found that the middleware would
insert the token, but the path would just get `None`. How‽ I tried to slowly
strip everything away from the non-functional path until it was identical to
this one, but it still would not work.
Well it turns out the solution was very simple, see this:
```rust
use my_package::storage::put_storage;
use crate::storage::delete_storage;
```
Ah! They are imported differently. I had set up my program as both a library and
a program for various reasons. However, it turns out importing the same thing
from `crate` is different from importing it from the library. Because of the
difference in import, Actix doesn't recognize that the types match, so the route
can't access the attached token.
The solution is normalizing the imports. I went with going through the library
for everything, because that's what `rust-analyzer`s automatic import seems to
prefer.
```rust
use my_package::storage::{put_storage, delete_storage};
```
Solved!

View File

@ -0,0 +1,35 @@
---
title: "Black Crown Initiate"
date: 2022-04-02
---
> This post is day 9 of me taking part in the
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
I love metal, I've been listening to metal since I was 13. It was the first
music genre that I actually liked: until I discovered metal I actually thought I
didn't like music at all, because nothing I heard on the radio or heard my
friends listening to were interesting to me. My taste in music has expanded and
changed over the years to include different types of music and genres, but metal
remains the one I love the most.
Demonstrating my metal-worthiness aside, I've always listened to European metal
bands. I had this weird elitist thought that "good" metal could only come from
Europe, with exceptions for some non-European bands, and that American metal was
just always bad. This is obviously false, but I just had never came across
anything American that I had liked. That's until recently.
I recently came across [Black Crown Initiate](https://www.metal-archives.com/bands/Black_Crown_Initiate/3540386765),
a progressive death metal band from Pennsylvania. And I have to tell you that they are amazing.
Their first release "Song of the Crippled Bull" is absolutely amazing. The music
is just the right amount of metal and progressive, and lyrics are amazing. The
clean vocals get the themes of the song across, while the growls give a lot of
power to the songs. My favorite songs from this release are "Stench of the Iron
Age" and the title track "Song of the Crippled Bull". Other hightlights from the
band I've listened to so far include "A Great Mistake", "Death Comes in
Reverse", "Vicious Lives".
I'm still making my way through their songs, but I'm glad to have discovered
something from America that I absolutely love. I'm now trying to find more
non-European bands that I enjoy.

View File

@ -0,0 +1,56 @@
---
title: An introduction to Bulgur Cloud - simple self hosted cloud storage
date: 2022-03-29
---
> This post is day 8 of me taking part in the
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
I've been recently working on Bulgur Cloud, a self hosted cloud storage
software. It's essentially Nextcloud, minus all the productivity software. It's
also designed to be much simpler, using no databases and keeping everything on
disk.
The software is still too early to actually demo, but the frontend is at a point
where I can show some features off. So I wanted to show it off.
![The login screen](/img/2022-03-29-00-17-38.png)
I've been going for a clean "print-like" look. I think it's going pretty well so far.
![The directory listing](/img/2022-03-29-00-16-13.png)
I'm not sure about the details of how the directory listing will look. I don't
think I like the upload button in the corner, and the rename and delete icons
feel like they would be easy to mis-press. There is a confirmation before
anything is actually deleted, but it still would be annoying.
![Delete confirmation prompt](/img/2022-03-29-00-20-48.png)
Something I'm pretty happy with is the file previews. I've added support for
images, videos, and PDFs. Video support is restricted by whatever formats are
supported by your browser, the server doesn't do any transcoding, but I think
it's still very useful for a quick preview. I'm also planning on support for
audio files. The server supports range requests, so you can seek around in the
video without waiting to download everything (although I've found that Firefox
doesn't handle that very well).
![Video file preview](/img/2022-03-29-00-22-48.png)
This is a web interface only so far, but I'm planning to add support for mobile
and desktop apps eventually. I've been building the interface with React Native
so adding mobile/desktop support shouldn't be too difficult, but I've been
finding that "write once, run everywhere" isn't always that simple. I ended up
having to add web-only code to support stuff like the video and PDF previews, so
I'll have to find replacements for some parts. Mobile and desktop apps natively
support more video and audio formats too, and with native code you usually have
the kind of performance to transcode video if needed.
The backend is written in Rust with `actix-web`, using async operations. It's
incredibly fast, and uses a tiny amount of resources (a basic measurement
suggests < 2 MB of memory used). I'm pretty excited about it!
After a few more features (namely being able to move files), I'm planning to put
together a demo to show this off live! The whole thing will be open source, but
I'm waiting until it's a bit more put together before I make the source public.
The source will go live at the same time as the demo.

View File

@ -0,0 +1,79 @@
---
title: Do kids not know computers now?
date: 2022-03-28
---
> This post is day 7 of me taking part in the
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
One discussion point I've seen around is that kids nowadays don't know how to
use computers. Okay that's a bit of a strawman, but this article titled [File Not Found](https://www.theverge.com/22684730/students-file-folder-directory-structure-education-gen-z).
The gist of the article is that Gen-Z kids are too used to search interfaces.
That means they don't actually know about where files are stored, or how they
are organized. They only know that they can access the files by searching for
them. The article talks about how professors ended up having to teach them how
to navigate directory structures and file extensions.
As the article claims, it seems to be related to how modern user interfaces are
designed. Our UIs nowadays are more focused around search capabilities: you just
type in a search bar and find what you need.
![bemenu, displaying a partial search and several matching applications.](/img/app-search-bar.png)
In some sense I do like this sort of interface. I use something like that when
launching applications, both on my Desktop and on my laptop! It's actually a
better interface compared to hunting for icons on your desktop. I use similar
interfaces in VSCode to switch between open editor tabs.
However, this is a complimentary interface to hierarchy and organization. Going
back to the file systems example discussed in the article, being able to search
through your files and folders is useful. But it's not a replacement for
hierarchy. You can't just throw files into a folder, and expect to always find
them accurately.
Let me give an example with Google Photos. I have been keeping all my photos on
Google Photos, and between migrating photos from old phones and ones I have
taken on new phones, I have over 8,000 photos. This is completely disorganized
of course, but Google Photos has a search functionality. It even uses AI to
recognize the items in the photos, which you can use in the search. A search for
"tree" brings up photos of trees, "cat" brings up cats, and you can even tag
people and pets and then search for their names. Very useful, right?
Well, it is sometimes. I recently had to remember what my wife's car license
plate is. A quick search for "license plate" on google photos and luckily, I had
taken a photo of her car that included the license plate in the frame. Success!
On the other hand, I was trying to find some photos from a particular gathering
with my friends. Searches for their names, names of the place, or stuff I know
are in the picture turned up with nothing. I eventually had to painstakingly
scroll through all photos to find the one I wanted.
This reminds me of 2 things. One is this article named [To Organize The World's
Information](https://dkb.io/post/organize-the-world-information) by
[@dkb868@twitter.com](https://nitter.net/dkb868). One thing I found interesting
on that article was that the concept of "the library" has been lost over the
last few decades as a way to organize information. They define the library as a
hierarchical, categorized directory of information. The article also talks about
other organizational methods, and is worth a read.
The other thing is the note taking software we're building at my workplace,
[Dendron](https://dendron.so/). One of the core tenets of Dendron is that the
information is hierarchical. Something the founder Kevin recognizes was that
other note taking software make it easier to make new notes, but they don't
support hierarchical structures which makes it hard to find those notes later.
I've also experienced this, when I used other note taking software (or sticky
notes!) I found that it was easy to just jot down a few notes, but they very
quickly get lost or hard to find when you need them. A hierarchical organization
makes it possible to actually find and reference the information later.
Requiring organization creates a barrier of entry to storing information, but
what good is storing information if you can't retrieve the information later?
This seems to work pretty well with Dendron. Would it not work for other things?
Why not for taking photos? You of course want to be able to quickly snap a photo
so you can record a moment before it's gone, but perhaps you could be required
to organize your photos afterwards. Before modern cellphones & internet
connected cameras, you'd have to get your photos developed or transfer them off
an SD card: a step where you would have to (or have the opportunity to) organize
your photos. I wonder if we cloud services could ask you to organize your photos
before syncing them as well.

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -10,3 +10,6 @@ page](https://github.com/SeriousBug).
I published several papers and participated in academic reviews during graduate school, which you can find [links to here](/publications/).
This website is also available on the gemini protocol as [gemini.bgenc.net](gemini://gemini.bgenc.net).
Please see the ["Clients" section on this page](https://gemini.circumlunar.space/software/)
to find a client, then connect to `gemini.bgenc.net`.

View File

@ -0,0 +1,60 @@
---
title: Mass batch processing on the CLI
date: 2022-03-19
---
> This post is day 4 of me taking part in the
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
Some time ago, I needed to process a lot of video files with vlc. This is
usually pretty easy to do, `for file in *.mp4 ; do ffmpeg ... ; done` is about
all you need in most cases. However, sometimes the files you are trying to
process are in different folders. And sometimes you want to process some files
in a folder but not others. That's the exact situation I was in, and I was
wondering if I needed to find some graphical application with batch processing
capabilities so I can queue up all the processing I need.
After a bit of thinking though, I realized I could do this very easily with a
simple shell script! That shell script lives in my [mark-list](https://github.com/SeriousBug/mark-list)
repository.
The idea is simple, you use the command to mark a bunch of files. Every file you
mark is saved into a file for later use.
```bash
$ mark-list my-video.mp4 # Choose a file
Marked 1 file.
$ mark-list *.webm # Choose many files
Marked 3 files.
$ cd Downloadsr
$ mark-list last.mpg # You can go to other directories and keep marking
```
You can mark a single file, or a bunch of files, or even navigate to other
directories and mark files there.
Once you are done marking, you can recall what you marked with the same tool:
```bash
$ mark-list --list
/home/kaan/my-video.mp4
/home/kaan/part-1.webm
/home/kaan/part-2.webm
/home/kaan/part-3.webm
/home/kaan/Downloads/last.mpg
```
You can then use this in the command line. For example, I was trying to convert everything to `mkv` files.
```bash
for file in `mark-list --list` ; do ffmpeg -i "${file}" "${file}.mkv" ; done
```
It works! After you are done with it, you then need to clear out your marks:
```
mark-list --clear
```
Hopefully this will be useful for someone else as well. It does make it a lot
easier to just queue up a lot of videos, and convert all of them overnight.

View File

@ -0,0 +1,44 @@
---
title: My response to Aurynn Shaw's "Contempt Culture" post
date: 2022-03-27
---
> This post is day 6 of me taking part in the
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
I recently came across [Aurynn Shaw's article on "Contempt Culture"](https://blog.aurynn.com/2015/12/16-contempt-culture/).
I'm a bit late to the party, but I wanted to talk about this too.
Aurynn's article talks about how some programming languages are considered
inferior, and programmers using these languages are considered less competent.
It's a good article, and you should take a look at it if you haven't.
## my thoughts
One thing I've come to realize over the years is that there are really no "bad
programming languages". Ignoring esolangs like brainfuck which are not really
meant to be used for anything serious, most programming languages are designed
to fit a niche. I'm using the term like it's used in ecology: every programming
language has a place in the ecosystem of technology and programming.
PHP is bad? PHP certainly has its drawbacks, but it also has its advantages.
"Drop these files into a folder and it works" is an amazing way to get started
programming. It's also a great way to inject a bit of dynamic content into
otherwise static pages. In fact, it's simpler and more straightforward solution
than building a REST API and a web app where you have to re-invent server side
rendering just to get back to where PHP already was!
That's not to say PHP is perfect or the best language to use. It's a language I
personally don't like. But that doesn't make it a bad or "stupid" programming
language. At worst it's a programming language that doesn't fit my needs. If I
extrapolate that and say that PHP is a bad language, that would instead show my
ego. Do I really think I'm so great that anything I don't like is just
immediately bad? Something Aurynn said resonates with me here:
> It didn't matter that it was (and remains) difficult to read, it was that we
> were better for using it.
I just want to conclude this with one thing: next time you think a programming
language or tool or whatever is bad, think to yourself whether that's because it
doesn't feel cool or because you saw others making fun of it, or because you
actually evaluated the pros and cons and came up with a calculated decision.

View File

@ -0,0 +1,91 @@
---
title: Running graphical user services with systemd
date: 2022-03-18
---
> This post is day 3 of me taking part in the
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
I've recently switched from KDE Plasma to sway as my window manager. I had a problem with the change though: the amazing kdeconnect service weren't working!
My first attempt at fixing this was to just add a lines into sway config to launch it along with sway.
```
exec /usr/lib/kdeconnectd
```
Looks simple enough. But for some reason, `kdeconnectd` would just disappear
after a while. It would appear to run at startup, and then an hour or two later
I pull up the kdeconnect app on my phone and it would tell me that my computer
is disconnected.
The biggest issue here was that I had no way to see why kdeconnect had failed.
In comes systemd to save the day. Systemd is a service manager, so it will
actually maintain the logs for these services. That means if kdeconnect is
crashing, I can check the logs for kdeconnect to see why it crashed. I can also
configure it to auto-restart after a crash if I want to.
To launch graphical applications with systemd though, you need to pass the
appropriate environment variables to it so it knows how to launch new windows.
I added this line to my sway config to do exactly that.
```
# Pass all variables to dbus & systemd to run graphical user services
exec dbus-update-activation-environment --all --systemd
```
Next, we need to write a service files to run the application. This is easier
than it sounds, here's the service file I wrote for kdeconnect:
```
[Unit]
Description=Run kdeconnectd.
After=graphical-session.target
StartLimitIntervalSec=600
StartLimitBurst=5
[Service]
Type=basic
ExecStart=/usr/lib/kdeconnectd
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=graphical-session.target
```
I saved this as `~/.config/systemd/user/kdeconnectd.service`. Finally, enabled it for my user with `systemctl --user enable kdeconnectd.service` and then restarted.
The service is configured to automatically restart on failure, but not if it
failed more than 5 times in the last 10 minutes. Systemd also waits 5 seconds
before trying to restart the failed service. This way if it crashes for some
reason, it will restart. But if it keeps crashing rapidly, it won't keep
trying to restart which could take up too much system resources.
I can now check how the service is doing with systemd!
```
Warning: The unit file, source configuration file or drop-ins of kdeconnectd.service changed on disk. Run 'systemctl --user daemon-reload>
● kdeconnectd.service - Run kdeconnectd.
Loaded: loaded (/home/kaan/.config/systemd/user/kdeconnectd.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2022-03-17 14:18:15 EDT; 1h 46min ago
Main PID: 2188363 (kdeconnectd)
Tasks: 6 (limit: 77007)
Memory: 24.2M
CPU: 2.440s
CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/kdeconnectd.service
└─2188363 /usr/lib/kdeconnectd
Mar 17 14:20:58 eclipse systemd[817]: /home/kaan/.config/systemd/user/kdeconnectd.service:6: Unknown key name 'type' in section 'Service'>
Mar 17 15:16:11 eclipse kdeconnectd[2188363]: QObject::connect(KWayland::Client::Registry, Unknown): invalid nullptr parameter
Mar 17 15:16:11 eclipse kdeconnectd[2188363]: kdeconnect.plugin.battery: No Primary Battery detected on this system. This may be a bug.
Mar 17 15:16:11 eclipse kdeconnectd[2188363]: kdeconnect.plugin.battery: Total quantity of batteries found: 0
Mar 17 15:23:26 eclipse kdeconnectd[2188363]: QObject::connect(KWayland::Client::Registry, Unknown): invalid nullptr parameter
Mar 17 15:23:26 eclipse kdeconnectd[2188363]: kdeconnect.plugin.battery: No Primary Battery detected on this system. This may be a bug.
Mar 17 15:23:26 eclipse kdeconnectd[2188363]: kdeconnect.plugin.battery: Total quantity of batteries found: 0
Mar 17 15:23:26 eclipse kdeconnectd[2188363]: QMetaObject::invokeMethod: No such method KIO::StoredTransferJob::slotDataReqFromDevice()
Mar 17 15:24:35 eclipse kdeconnectd[2188363]: QMetaObject::invokeMethod: No such method KIO::StoredTransferJob::slotDataReqFromDevice()
Mar 17 15:57:29 eclipse systemd[817]: /home/kaan/.config/systemd/user/kdeconnectd.service:9: Unknown key name 'type' in section 'Service'>
```
A bunch of warnings so far, but no crashes yet. But if it does crash again, I'll finally know why.

View File

@ -0,0 +1,47 @@
---
title: A little type system trick in Rust
date: 2022-03-15
---
> This post is day 1 of me taking part in the
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
While working on a small project recently, I ended up writing this type in Rust.
```rust
type ImageData = Arc<Mutex<Option<ImageBuffer<Rgba<u8>, Vec<u8>>>>>;
```
Even though I wrote it myself, it actually took me a bit after writing it to
figure out what this type was doing so I wanted to write about it.
Let me start from outside-in, the first type we have is `Arc`. `Arc` stands for
"atomic reference counting". [Reference counting](https://en.wikipedia.org/wiki/Reference_counting)
is a method to handle ownership of the data, or in other words to figure out
when the data needs to be freed. Garbage collected languages do this
transparently in the background, but in Rust we explicitly need to state that we
want it. Atomic means this is done using [atomic operations](https://en.wikipedia.org/wiki/Linearizability#Primitive_atomic_instructions),
so it is thread safe. In my case, I needed this because this data was going to
be shared between multiple threads, and I didn't know exactly when I would be "done"
with the data.
The next type is `Mutex`, which means [mutual exclusion](https://en.wikipedia.org/wiki/Lock_(computer_science))
or locking. Locks are used to restrict access to data to a single thread at a time.
That means whatever type is inside of this is not thread safe,
so I'm using the lock to protect it. Which is true!
The type after that is `Option`. This basically means "nullable", there may or may not be a thing inside this.
The interesting thing here is that this is a [sum type](https://en.wikipedia.org/wiki/Tagged_union),
so Rust helps remind us that this is nullable without introducing a nullability concept to the language. It's just part of the type system!
Then we have `ImageBuffer`, a type from the popular [image crate](https://docs.rs/image/latest/image/index.html).
Not much to talk about with this, that's the data I wanted to store.
The next thing that *is* interesting is the `Rgba<u8>` and `Vec<u8>` inside the image buffer.
What that means (and I'm speculating here because I'm lazy/too busy to check), is that
`Rgba` is just a basic wrapper type (or a "newtype"). It makes the compiler enforce the type of the
image data that's stored in this image buffer, so the user doesn't mix up different data types.
Similar for `Vec<u8>`, (I think) it means that the data inside this buffer is stored in a vector.
Finally, `u8` is probably self descriptive, the pixels and the vector are made out of 8-bit unsigned integers.

View File

@ -0,0 +1,83 @@
---
title: State of Rust GUIs
date: 2022-03-17
---
> This post is day 2 of me taking part in the
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
The website [Are we GUI Yet?](https://www.areweguiyet.com/) helpfully lists a
lot of the libraries and frameworks available for making a GUI in Rust. I've
been looking into making a GUI program in Rust, so I've been working my way
through some of these options.
This is not a through review, just my thoughts after a brief look. I'd recommend
looking over the website and deciding for yourself.
## Best candidate: Dioxus
- Website: https://dioxuslabs.com/
Dioxus is probably the option I like the best from a quick look. Declarative
applications similar to React, encapsulated components, first class async
support, and good type checking.
Downsides? Right now it's web only. Desktop applications are just web
applications rendered inside a web view. That's okay for cross platform apps,
but not for what I want to do which is a lightweight native application.
## Better Electron: Tauri
- Website: https://github.com/tauri-apps/tauri
Tauri is a really good replacement for Electron. You can see the comparison on
their Github page, smaller binaries, less memory use, and faster launch times.
But again, it is a web app running in a web view. Not a native desktop app. Even
though Tauri uses less memory than electron, it still uses ~180 MB according to
their comparison. And the fast launch time is still around 0.4 seconds, way
longer than what I would expect.
## My current preference: Slint
- Website: https://slint-ui.com/
I really like Slint. It is a native GUI with their own OpenGL renderer, and an
optional Qt backend. From some basic experimentation, it seems to launch in less
than 50ms, and uses less than 80 MB of memory (mostly shared libraries).
You can write the code in either `.slint` files (and they actually have okay
editor support for this file type), or inside macros in your code files. The
code also looks pretty intuitive.
The downsides? The theming support is not great/nonexistent, you can't
dynamically generate UI elements (well kinda, you can generate them based on
properties you change at runtime, but the components themselves are hardcoded),
and the code sometimes gets awkward due to current limitations.
```rust
MainWindow := Window {
// You then have to bind to this callback inside rust code. No way to just write a hook that calls a rust function.
callback save_to_file(string);
HorizontalLayout {
height: 32px;
FilePath := LineEdit {
placeholder_text: "placeholder here";
}
Button {
text: "Save to file";
clicked => { save_to_file(FilePath.text); }
}
}
}
```
There is also no way to do some things, like setting a dialog hint for your main
window, which is something I needed to do.
## Conclusion?
It looks like the state of GUIs in rust is still "not yet". There are a few more
projects I need to look at, like [Relm](https://github.com/antoyo/relm), but
their code looks way too verbose to me. In the end, I think the best option
might be to just write my GUI in C++ with Qt, and maybe integrate bits written
in rust inside of that.

36
gemini/_index.gmi Normal file
View File

@ -0,0 +1,36 @@
# Homepage of Kaan Barmore-Genç
Hey folks!
I'm a Software Engineer at Dendron, and a recent Master's graduate from the Ohio
State University. I'm an avid Linux user, an enthusiast of many programming
languages, a home cook, and an amateur gardener.
=> https://dendron.so Dendron
=> https://bgenc.net/recipes/ My recipes
My interests include building web and mobile applications, both at the front and
back end. Over the years I learned and used many programming languages and
technologies, including JavaScript, TypeScript, React, React Native, Rust,
Python, Java, C, C++, Clojure, and Haskell. Pretty much everthing I've worked on
is open source and available on my Github page.
I published several papers and participated in academic reviews during graduate school. You can find them below.
=> /publications.gmi My publications
Here are some links if you need to reach me.
=> mailto:kaan@bgenc.net kaan@bgenc.net
=> /extra/kaangenc.gpg GPG key
=> https://github.com/SeriousBug Github
=> https://www.linkedin.com/in/kaan-genc-8489b9205/ LinkedIn
=> /extra/cv.pdf My CV
=> https://mastodon.technology/@kaan My Mastodon
This page is also available on HTTP/HTML if you prefer that.
=> https://bgenc.net HTTP mirror
Finally, below is a list of all my blog posts. These are not sorted by date at the moment, but I'm working on fixing that soon.

View File

@ -21,7 +21,7 @@
(when (not= slug "index") [:a.home {:href "/"} "Home"])
[:img.picture {:alt "A photo of Kaan, after his OOPSLA 2019 talk." :src "/img/profile.jpg"}]
[:div.name "Kaan Barmore-Genç"]
[:div.title "M.S. Software Engineer"]
[:div.title "M.S."]
[:div.spacer]
[:div.title "Software Engineer"]
[:div.affiliation [:a {:href "http://dendron.so/"} "Dendron"]]