hallettj

joined 1 year ago
[–] hallettj@leminal.space 2 points 2 days ago

The Android app is also bad. They never figured out how to use the correct fullscreen API, so you see the white bar / soft button at the bottom while videos are playing. And they didn't get the media API right either so bluetooth headset play/pause buttons don't work.

[–] hallettj@leminal.space 3 points 2 days ago

That makes sense. I didn't find many surveys available, so I referenced the ones I could find.

[–] hallettj@leminal.space 8 points 2 days ago (3 children)

It's hard to predict the future, but I can point to a couple of indexes.

TIOBE measures language popularity according to a variety of factors. It has Java on a steady downward trend over the last couple of decades, but shows it as still very relevant. TIOBE does not show comparable growth for Golang. I don't see much growth in the top 10 for languages that are especially suited to autoscaling. C# looks to be steady as a language in a similar niche as Java.

OTOH another survey from devjobsscanner that looks purely at job postings shows Java openings as very steady over the last couple of years. It also shows Java as more popular than Golang.

So I don't know exactly what conclusion to draw from that. But learning a new language can be a helpful exercise regardless to broaden your perspective, and to keep your skills sharp.

Personally for the purpose of producing resource-efficient binaries for scaling I prefer Rust. It's design incorporates some correct-by-construction strategies that promote high-quality code. And it's well-suited for compiling to WASM so you can do stuff like deploy small services to Cloudflare workers for wild scaling. But I guess Rust isn't making a big showing in the popularity charts. And Golang is popular for its lower learning curve.

[–] hallettj@leminal.space 9 points 3 days ago

Hmm, good point. The pig AI requires a lot more computations than wheat or pumpkins which are managed by random tick updates.

[–] hallettj@leminal.space 3 points 4 days ago

You have two options depending on how you set your Typescript config.

Option 1, the default:

declare const xs: number[]
const x = xs[4] // inferred type is `number`

Option 2, using the noUncheckedIndexedAccess setting:

declare const xs: number[]
const x = xs[4] // inferred type is `number | undefined`

Your AI assistant appears to assume option 2. Maybe you have that option enabled in your project?

I'm sorry you had to spend a lot of time and frustration on this problem. But fundamentally Rust and Typescript have the same limitation: neither will catch out-of-bounds access errors on variable-length collections at type-checking time. They don't have the necessary information to do that.

Rust can catch out-of-bounds access on a fixed-length array if you use a literal number for the index access. But Typescript can do the same thing if you use a fixed-length tuple type (e.g. [number, number] instead of number[]).

[–] hallettj@leminal.space 5 points 1 week ago

I agree that The Visitor is a great choice! Although depending on OP's goal I'd argue for Duet because,

  • It's another excellent, self-contained story
  • It keeps the story in the usual space station setting
  • You get more time with the regular cast (IIRC)
  • There is less hand-wavy scifi stuff going on

So it might be a simpler introduction to the rest of the show.

Those factors aside, yeah The Visitor is probably the more compelling story.

Either way, DS9 has the best character writing, and is therefore the way to go!

[–] hallettj@leminal.space 3 points 1 week ago

If you're getting started with programming the first resource I point people to is Scratch. It's the easiest way to get started, and teaches programming concepts with guide-rails. I recommend looking at a game someone else has made on the Scratch website, and "remixing" it to tinker, and understand how it works.

When you hit the limitations of Scratch, and want more I agree with other commenters that Godot or LÖVE are good next steps.

[–] hallettj@leminal.space 3 points 2 weeks ago (1 children)

Is Tuvix managing other positions single-handed, or are there many Tuvices?

[–] hallettj@leminal.space 9 points 2 weeks ago (1 children)

You might be interested to learn some history of societies without state-issued currency. The book "Debt: The First 5000 years" by David Graeber has lots to say about pre-modern systems of account. I'm aware there are some criticisms of the book so I don't want present it as absolute truth - but it is an interesting on read, and it cites lots of anthropological studies.

One of the points of the book - and I see there are also other anthropologists who take this view - is there is no evidence that there has ever been a barter economy. Economics curriculum typically talks about prehistoric barter as an introduction; but it looks like the barter story may have been made up by Adam Smith. Smith's "Wealth of Nations" is highly insightful, and even predicts problems with capitalism that we currently face. But he probably didn't have the anthropological background to write authoritatively about economies of prehistoric societies.

Graeber does claim that there have been times when barter has been a stop-gap when there is a problem with money supply. So that's a case where something like your app might come in,

When barter has appeared, it wasn’t as part of a purely barter economy, and money didn’t emerge from it—rather, it emerged from money. After Rome fell, for instance, Europeans used barter as a substitute for the Roman currency people had gotten used to. “In most of the cases we know about, [barter] takes place between people who are familiar with the use of money, but for one reason or another, don’t have a lot of it around.

These were temporary situations. The fall of Rome probably seemed like the end of the world to some people at the time. But new societal structures and currencies filled the gaps.

[–] hallettj@leminal.space 2 points 2 weeks ago (1 children)

May I ask what brand of LECA you use? I've read contradictory things about pH of LECA being basic. I got a bag of Growit, and tested it with tap water - the water is indeed very basic compared to my control even after lots of rinsing and repeated soakings. I'm wondering if some brands are better at living up to claims of being pH neutral than others.

[–] hallettj@leminal.space 3 points 3 weeks ago

I do the same - except I upgraded to 64 GB at a point in my life when I was doing Haskell programming on a largish project, and I learned that 32 GB is not sufficient to run the LSP and the compiler at the same time.

251
submitted 1 month ago* (last edited 1 month ago) by hallettj@leminal.space to c/mycology@mander.xyz
 

Update: The first photo was day 3 of growing. We harvested on day 4, and got 255 grams of tasty snack!

 

I got into bullet journaling a few weeks ago. I looked at a bunch of resources that went into detail, but I felt like I didn't have the big picture. The Absolute Ultimate Guide covers the motivation, what bullet journaling is all about, and details for getting started quickly, all in one relatively short post.

 

I'm trying to write a Nix package for a closed-source, precompiled binary with an unusual twist. The binary is statically-linked, but it contains an embedded binary that is dynamically-linked. Is there some way I can use patchelf or another tool to path the interpreter path in the embedded binary?

The embedded binary does not have any runtime library dependencies, but it does need an interpreter which it expects at the hard-coded path /lib64/ld-linux-x86-64.so.2. It is embedded using the golang "embed" library.

I have a workaround that wraps the binary using buildFHSEnv. That works, but the resulting closure is about 300 MB bigger than it needs to be.

 

The situation: you're trying to build something, but one of your configured substituters (a.k.a binary caches) is either offline, or having a moment of being very slow. Nix doesn't automatically time out, and skip that cache. No, you just can't build. You want to disable the problem cache so you can get on with your life. But since you use NixOS you need to run nixos-rebuild to update your substituter settings. A rebuild means hitting the problem cache...

When I've run into this problem I've thought, "I really need a way to selectively disable a cache in the nix build command." Previously I've had a hard time searching for such an option. Today I found it! Here it is:

$ nix build --option substituters "https://cache.nixos.org/ https://nix-community.cachix.org/"

or

$ nixos-rebuild build --option substituters "https://cache.nixos.org/ https://nix-community.cachix.org/"

The flag --option overrides settings that are normally read from /etc/nix/nix.conf. The idea here is instead of specifying a cache to disable, you list all of the caches that you do want to use.

Unless you are running as a "trusted user" you can't use this method to use substituters that aren't already configured because that would be a security problem. That means that substituter URLs need to be exactly the same as they are specified in /etc/nix/nix.conf including query parameters like ?priority.

I run into the misbehaving cache problem in two situations:

  • From time to time I get an error from cachix. I think it might be something like the cache claims to have a store path, but then actually downloading it fails. I'm not sure. Anyway the cache error makes the whole build command fail.
  • Sometimes garnix, as helpful as it is for avoiding expensive rebuilds on my slow laptop, gets very slow serving large packages like slack and google-chrome. These are unfree so they aren't cached on cache.nixos.org which usually takes precedence over garnix for unmodified nixpkgs packages. But since I build my nixos config on garnix the unfree packages do get cached there. I could wait all day for my nixos rebuild, or I could bypass the cache, download binaries from their original URLs, and be done in seconds.
26
submitted 6 months ago* (last edited 6 months ago) by hallettj@leminal.space to c/nix@programming.dev
 

I'm a fan of gaming - my main game is Overwatch. Until this week I've been using xwayland or gamescope to run Wine games which comes with downsides. Xwayland's window management can be buggy - in Gnome I can end up unable to switch back to a game window. Gamescope has some latency and visual artifact issues in my preferred window manager.

But now with the Wine 10 release candidates you can run Wine in native Wayland mode without any special registry settings or anything. And it works very well as far as I can tell! I went through the trouble of figuring out how to get Wine 10 set up on NixOS so I thought I would share.

Wine 10 is currently available in nixos-unstable. The simplest way I've found to get it working for games is to use Lutris, and to install both Lutris and Wine from unstable. To get a complete Wine setup for Lutris use wineWowPackages - for example wineWowPackages.stagingFull. The Full variant includes wine-mono which you'll probably want, and the staging package is the one that worked for me.

I have an overlay that lets me reference unstable packages via pkgs.unstable.${package-name}. With that in place I have this in my NixOS settings:

environment.systemPackages = [
  (pkgs.unstable.lutris.override {
    extraPkgs = pkgs: [
#               ----
#      ↓ same var ↑ 
#     ---- 
      pkgs.wineWowPackages.stagingFull
      pkgs.winetricks
    ];
  })
];

Note that you'll want to use the shadowed pkgs variable introduced in the function given to extraPkgs to reference the wine packages. I think that package set has some extra FHS stuff done to it or something.

If you don't have it already the shortcut for enabling necessary system settings for running games with Vulkan is to enable steam:

programs.steam.enable = true;

You can presumably put the Lutris configuration in Home Manager instead of NixOS by setting home.packages instead of environment.systemPackages. The steam setting needs to be set in NixOS.

When you run Lutris change the Wine runner settings to use the "system default" Wine version, and check the "use system winetricks" toggle.

To make sure that Wine uses Wayland you can unset the DISPLAY environment variable, or set it to an empty string. To do that in Lutris go into the game configuration settings. Under the "System options" tab add an environment variable named DISPLAY, and leave its value empty.

And that's it!

The one issue I've run into is that the Battle.net launcher is a blank black rectangle. The workaround is to run the launcher in gamescope or xwayland, install the game you want, and then re-launch without gamescope in native Wayland. You can start the game you want using the menu from Battle.net's system tray icon so that you don't need to use the launcher UI.

Edit: Thanks @vividspecter@lemm.ee for the point about unsetting DISPLAY!

Edit: @BlastboomStrice@mander.xyz pointed out that all of the Wine packages on unstable are updated to v10 so I changed the instructions to use stableFull instead of stagingFull.

Edit: stableFull wasn't actually working for me so I switched the instructions back to stagingFull

 

Logan Smith's Rust videos are excellent - I'm happy to see a new one is up!

14
submitted 9 months ago* (last edited 9 months ago) by hallettj@leminal.space to c/linux@lemmy.ml
 

Some app launchers these days run each app in a new systemd scope, which puts the app process and any child processes into their own cgroup. For example I use rofi which does this, and I noticed that fuzzel does also. That is handy for tracking and cleaning up child processes!

You can see how processes are organized by running,

$ systemctl --user status

I think that's a quite useful way to see processes organized. Looking at it I noticed a couple of scopes that shouldn't still be running.

Just for fun I wanted to use this to try to script a better killall. For example if I run $ killscope slack I want the script to:

  1. find processes with the name "slack"
  2. find the names of the systemd scopes that own those processes (for example, app-niri-rofi-2594858.scope)
  3. kill processes in each scope with a command like, systemctl --user stop app-niri-rofi-2594858.scope

Step 2 turned out to be harder than I liked. Does anyone know of an easy way to do this? Ideally I'd like a list of all scopes with information for all child processes in JSON or another machine-readable format.

systemctl --user status gives me all of the information I want, listing each scope with the command for each process under it. But it is not structured in an easily machine-readable format. Adding --output json does nothing.

systemd-cgls shows the same cgroup information that is shown in systemctl --user status. But again, I don't see an option for machine-readable output.

systemd-cgtop is interesting, bot not relevant.

Anyway, I got something working by falling back on the classic commands. ps can show the cgroup for each process:

$  ps x --format comm=,cgroup= | grep '^slack\b'
slack           0::/user.slice/user-1000.slice/user@1000.service/app.slice/app-niri-rofi-2594858.scope
slack           0::/user.slice/user-1000.slice/user@1000.service/app.slice/app-niri-rofi-2594858.scope
slack           0::/user.slice/user-1000.slice/user@1000.service/app.slice/app-niri-rofi-2594858.scope
...

The last path element of the cgroup happens to be the scope name. That can be extracted with awk -F/ '{print $NF}' Then unique scope names can be fed to xargs. Here is a shell function that puts everything together:

function killscope() {
    local name="$1"
    ps x --format comm=,cgroup= \
        | grep "^$name\b" \
        | awk -F/ '{print $NF}' \
        | sort | uniq \
        | xargs -r systemctl --user stop
}

It could be better, and it might be a little dangerous. But it works!

 

A short post on how variable names can leak out of macros if there is a name collision with a constant. I thought this was a delightful read!

 

Difftastic is a diff tool that uses treesitter parsing to compare code AST nodes instead of comparing lines. After following the instructions for use with git I'm seeing some very nice diffs when I run git diff or run git show --ext-diff. I thought it would be nice to get the same output for hunk diffs in the fugitive status window, and in fugitive buffers in general (which use the git filetype). But I haven't seen any easy way to do it. Has anyone got a setup like this?

I can run a command in neovim like :Git show --ext-diff to get difftastic output in a buffer. I'm thinking maybe I can set up fugitive to use the --ext-diff flag by default, or set up some aliases. But there is no syntax highlighting for the difftastic outputs since the ANSI color codes that difftastic uses in interactive terminal output don't work in neovim, and the syntax highlighting for the git filetype assumes standard diff output which is not compatible with difftastic output. For me losing colors is not a worthwhile trade for the otherwise more readable diff output.

My best idea right now is to set up a new filetype called difftastic, and write a new treesitter grammar or syntax plugin for it. Then set up some kind of neovim configuration to feed output from difftastic into buffers with the new filetype.

There is an open neovim issue discussing adding syntax-aware diffs directly to neovim, but that doesn't seem to have gone anywhere.

 

I installed StarCraft: Mass Recall which is an impressive project that recreates the original StarCraft and Brood War campaigns in StarCraft 2. Everything works except that the cinematics and some of the game assets are flat, blank red. For example some of the video portraits in the briefing rooms display correctly, but Mengsk is a solid red square. In the first mission Raynor's vulture is flat red while everything else looks correct. Sound works correctly including in cinematics.

The game assets aren't a huge deal, but the cinematics are a big part of the reason for playing these campaigns IMO.

I've tried everything I can think of. I tried some different Wine runners. I tried disabling DXVK. I installed a number of dependencies that look like they provide video codecs:

  • amstream
  • devenum
  • quartz
  • xvid
  • ffdshow

Does anyone have ideas about what else I might try?

What I did figure out is a working command to run the mod, which took me a while. I used Bottles, installed Battle.net through the Bottles program installer, installed StarCraft 2 via Battle.net, and finally installed Mass Recall by unzipping and copying its files to the StarCraft Maps/ and Mods/ directories. Then I was able to run Mass Recall with this command:

$ bottles-cli shell -b "<bottle name>" -i '"C:\Program Files (x86)\StarCraft II\Support64\SC2Switcher_x64.exe" "C:\Program Files (x86)\StarCraft II\Maps\Starcraft Mass Recall\SCMR Campaign Launcher.SC2Map"'
43
submitted 1 year ago* (last edited 1 year ago) by hallettj@leminal.space to c/linux@lemmy.ml
 

Passkeys seem like a great idea, and we are at a point where, although things are still very much in flux, software passkeys managed by password managers are starting to be usable. I thought I'd share the workflow that's working for me on Linux with some sites, and ask the community for more tips & tricks.

A passkey is a client certificate - which is an old idea, but now there are some new standards in place*. When you log into a website, instead of sending a password you send a message signed using the private key on your hardware security device, or stored in your password manager. If you use a password manager the flow is about the same as with passwords: your password manager pops up and asks if you want to log in to the given website. But instead of sending a password to the browser, message signing takes place in the password manager. Unlike passwords those signed messages can't be replayed. Arguably you can skip sending MFA codes and get about the same (or maybe better) security with passkeys than you were getting with passwords + MFA.

Complications come up because support for passkey APIs is still patchy. On Linux I think there is system-level support for hardware keys, but not for passkey managers (password managers that can do passkey signing). But you can close that gap using browser extensions! I'm using Enpass with it's Firefox extension. Signing into websites in Firefox using passkeys works quite well in some of the sites I've tried. (I've also tested with Bitwarden's browser extension, and it works just as well.**) Although creating passkeys doesn't work on all of those sites.

  • I was able to create a passkey on Github, and sign in with it.
  • I was able to create a passkey for the demo at https://www.passkeys.io/, and sign in with it.
  • I couldn't create passkeys for Google, but I could log in with passkeys created on another device, and synced by Enpass to my Linux machine.
  • I can use a passkey for MFA on Discord, but they don't seem to be using them for logins yet.
  • I'm not getting options to use my passkeys on Amazon or Paypal, but I was able to create passkeys for these sites on Android.

Without using a browser extension Chrome on Linux does have a feature to sign in with passkeys on mobile devices. I don't think this works with third-party passskey managers. On some sites Chrome gave me the option to log in using the automatically-generated, Google-managed passkey on my phone. It didn't actually worked for me - my phone showed a message saying "connecting to device" but never actually connected.

That brings me to the Android side. Since some sites will let me log in with passkeys but not create them it's helpful to have another option for creating passkeys. Android is further along in implementing system level passkey support (only in Android 14 or later). But it's not perfect yet. Firefox for Android is not working with passkey managers yet, but there is a ticket to track this. Third-party passkey managers work in Chrome for Android, but only if you enable an experimental flag:

  • open chrome://flags/
  • find the setting "Android Credential Management for passkeys"
  • set the value to "Enabled for Google Password Manager and 3rd party passkeys"

* "Passkey" seems to be an umbrella term for WebAuthn or FIDO U2F. It looks like WebAuthn is a part of FIDO2.

** From a cursory look at the two I feel more comfortable with Enpass' browser extension than with Bitwarden's. I'm not positive, but it looks like Bitwarden loads credentials in the extension itself which puts all of your secrets in the browser process. OTOH the Enpass extension uses IPC to send requests to the Enpass desktop app. But as many will point out, Bitwarden's clients are open-source and audited while Enpass' software is closed-source.

 

cross-posted from: https://leminal.space/post/4750886

It took me some time to work out how to get my ssh agent set up in Niri so I though I would share what I did. I'm using NixOS and Home Manager. I put this in my Home Manager config:

services.gnome-keyring = {
  enable = true;
  components = [ "pkcs11" "secrets" "ssh" ];
};
home.sessionVariables.SSH_AUTH_SOCK = "$XDG_RUNTIME_DIR/keyring/ssh";

I'm using GDM according to NixOS' default configuration which I think runs gnome-keyring (I thought I saw it in the process list before I set up the user unit), and I think that configuration is automatically unlocking gnome-keyring when I log in via PAM integration. But apparently I need to run gnome-keyring again in my window manager session. Home Manager's services.gnome-keyring adds a systemd user unit that does that.

view more: next ›