Full Width [alt+shift+f] Shortcuts [alt+shift+k]
Sign Up [alt+shift+s] Log In [alt+shift+l]
6
I recently came upon a horror story where a developer was forced to switch editor from Neovim to Cursor and I felt I had to write a little to cleanse myself of the disgust I felt. Two different ways of approaching an editor I think that there’s two opposing ways of thinking about the tool that is an editor: Refuse to personalize anything and only use the basic features “An editor is a simple tool I use to get the job done.” Get stuck in configuration hell and spend tons of time tweaking minor things “An editor is a highly personalized tool that works the way I want.” These are the extreme ends of the spectrum to make a point and most developers will fall somewhere in between. It’s not a static proposition; I’ve had periods in my life where I’ve used the same Vim configuration for years and other times I’ve spent more time rewriting my Neovim config than doing useful things. I don’t differentiate between text editors and IDEs as I don’t find the distinction very meaningful. They’re all...
2 days ago

Improve your reading experience

Logged in users get linked directly to articles resulting in a better reading experience. Please login for free, it takes less than 1 minute.

More from Jonas Hietala

Securing my partner's digital life

I’ve been with Veronica for over a decade now and I think I’m starting to know her fairly well. Yet she still manages to surprise me. For instance, a couple of weeks ago she came and asked me about email security: I worry that my email password is too weak. Can you help me change email address and make it secure? It was completely unexpected—but I’m all for it. The action plan All heroic journeys needs a plan; here’s mine: .com surname was available). Migrate her email to Fastmail. Setup Bitwarden as a password manager. Use a YubiKey to secure the important services. Why a domain? If you ever want (or need) to change email providers it’s very nice to have your own domain. For instance, Veronica has a hotmail.com address but she can’t bring that with her if she moves to Fastmail. Worse, what if she gets locked out of her Outlook account for some reason? It might happen if you forget your password, someone breaks into your account, or even by accident. For example, Apple users recently got locked out of their Apple IDs without any apparent reason and Gmail has been notorious about locking out users for no reason. Some providers may be better but this is a systemic problem that can happen at any service. In almost all cases, your email is your key to the rest of your digital life. The email address is your username and to reset your password you use your email. If you lose access to your email you lose everything. When you control your domain, you can point the domain to a new email provider and continue with your life. Why pay for email? One of the first things Veronica told me when I proposed that she’d change providers was that she didn’t want to pay. It’s a common sentiment online that email must be cheap (or even free). I don’t think that email is the area where cost should be the most significant factor. As I argued for in why you should own your email’s domain, your email is your most important digital asset. If email is so important, why try to be cheap about it? You should spend your money on the important things and shouldn’t spend money on the unimportant things. Paying for email gives you a couple of nice things: Human support. It’s all too easy to get shafted by algorithms where you might get banned because you triggered some edge case (such as resetting your password outside your usual IP address). Ability to use your own domain. Having a custom domain is a paid feature at most email providers. A long-term viable business. How do you run an email company if you don’t charge for it? (You sell out your users or you close your business.) Why a password manager? The best thing you can do security wise is to adopt a password manager. Then you don’t have to try to remember dozens of passwords (leading to easy-to-remember and duplicate passwords) and can focus on remembering a single (stronger) password, confident that the password manager will remember all the rest. “Putting all your passwords in one basket” is a concern of course but I think the pros outweigh the cons. Why a YubiKey? To take digital security to the next level you should use two-factor authentication (2FA). 2FA is an extra “thing” in addition to your password you need to be able to login. It could be a code sent to your phone over SMS (insecure), to your email (slightly better), a code from a 2FA app on your phone such as Aegis Authenticator (good), or from a hardware token (most secure). It’s easy to think that I went with a YubiKey because it’s the most secure option; but the biggest reason is that a YubiKey is more convenient than a 2FA app. With a 2FA app you have to whip out your phone, open the 2FA app, locate the correct site, and then copy the TOTP code into the website (quickly, before the code changes). It’s honestly not that convenient, even for someone like me who’s used this setup for years. With a YubiKey you plug it into a USB port and press it when it flashes. Or on the phone you can use NFC. NFC is slightly more annoying compared to plugging it in as you need to move/hold it in a specific spot, yet it’s still preferable to having to jump between apps on the phone. There are hardware keys other than YubiKey of course. I’ve used YubiKey for years and have a good experience. Don’t fix what isn’t broken. The setup Here’s a few quick notes on how I setup her new accounts: Password management with Bitwarden The first thing we did was setup Bitwarden as the password manager for her. I chose the family plan so I can handle the billing. To give her access I installed Bitwarden as: I gave her a YubiKey and registered it with Bitwarden for additional security. As a backup I also registered my own YubiKeys on her account; if she loses her key we still have others she can use. Although it was a bit confusing for her I think she appreciates not having to remember a dozen different passwords and can simply remember one (stronger) password. We can also share passwords easily via Bitwarden (for news papers, Spotify, etc). The YubiKey itself is very user friendly and she hasn’t run into any usability issues. Email on Fastmail With the core security up and running the next step was to change her email: Gave her an email address on Fastmail with her own domain (<firstname>@<lastname>.com). She has a basic account that I manage (there’s a Duo plan that I couldn’t migrate to at this time). I secured the account with our YubiKeys and a generated password stored in Bitwarden. We bolstered the security of her old Hotmail account by generating a new password and registering our YubiKeys. Forward all email from her old Hotmail address to her new address. With this done she has a secure email account with an email address that she owns. As is proper she’s been changing her contact information and changing email address in her other services. It’s a slow process but I can’t be too critical—I still have a few services that use my old Gmail address even though I migrated to my own domain more than a decade ago. Notes on recovery and redundancy It’s great to worry about weak phishing, weak passwords, and getting hacked. But for most people the much bigger risk is to forget your password or lose your second factor auth, and get locked out that way. To reduce the risk of losing access to her accounts we have: YubiKeys for all accounts. The recovery codes for all accounts are written down and secured. My own accounts can recover her Bitwarden and Fastmail accounts via their built-in recovery functionality. Perfect is the enemy of good Some go further than we’ve done here, others do less, and I think that’s fine. It’s important to not compare yourself with others too much; even small security measures makes a big difference in practice. Not doing anything at all because you feel overwhelmed is worse than doing something, even something simple as making sure you’re using a strong password for your email account.

a month ago 31 votes
First impressions of Ghostty

There are two conflicting forces in play in setting up your computer environment: It’s common to find people get stuck at the extreme ends of the spectrum; some programmers refuse to configure or learn their tools at all, while others get stuck re-configuring their setups constantly without any productivity gains to show for it. Finding a balance can be tricky. With regards to terminals I’ve been using alacritty for many years. It gets the job done but I don’t know if I’m missing out on anything? I’ve been meaning to look at alternatives like wezterm and kitty but I never got far enough to try them out. On one hand it’s just a terminal, what difference could it make? Enter Ghostty, a terminal so hyped up it made me drop any useful things I was working on and see what the fuzz was about. I don’t quite get why people hype up a terminal of all things but here we are. Ghostty didn’t revolutionize my setup or anything but I admit that Ghostty is quite nice and it has replaced alacritty as my terminal. I just want a blank canvas without any decorations One of the big selling points of Ghostty is it’s native platform integration. It’s supposed to integrate well with your window manager so it looks the same and gives you some extra functionality… But I don’t know why I should care—I just want a big square without decorations of any kind. You’re supposed to to be able to simply turn off any window decorations: window-decoration = false At the moment there’s a bug that requires you set some weird GTK settings to fully remove the borders: gtk-titlebar = false gtk-adwaita = false It’s unfortunate as I haven’t done any GKT configuration on my machine (I use XMonad as my window manager and I don’t have any window decorations anywhere). There might some useful native features I don’t know about. The password input style is neat for instance, although I’m not sure it does anything functionally different compared to other terminals: Cursor invert cursor-invert-fg-bg = true In alacritty I’ve had the cursor invert the background and foreground and you can do that in Ghostty too. I ran into an issue where it interferes with indent-blankline.nvim making the cursor very hard to spot in indents (taking the color of the indent guides, which is by design low contrast with the background). Annoying but it gave me the shove I needed to try out different plugins to see if the problem persisted. I ended up with (an even nicer) setup using snacks.nvim that doesn’t hide the cursor: Left: indent-blankline.nvim (cursor barely visible) snacks.nvim (cursor visible and it highlights scope). Minimum contrast Unreadable ls output is a staple of the excellent Linux UX. It might look like this: Super annoying. You can of course configure the ls output colors but that’s just for one program and it won’t automatically follow when you ssh to another server. Ghostty’s minimum-contrast option ensures that the text and background always has enough contrast to be visible: minimum-contrast = 1.05 Most excellent. This feature has the potential to break “eye candy” features, such the Neovim indent lines plugins if you use a low contrast configuration. I still run into minor issues from time to time. Hide cursor while typing mouse-hide-while-typing = true A small quality-of-life feature is the ability to hide the cursor when typing. I didn’t know I needed this in my life. Consistent font sizing between desktop and laptop With alacritty I have an annoying problem where I need to use a very different font size on my laptop and my desktop (8 and 12). This wasn’t always the case and I think something may have changed in alacritty but I’m not sure. Ghostty doesn’t have this problem and I can now use the same font settings across my machines ( font-size = 16 ). Ligature support The issue for adding ligatures to alacritty was closed eight years ago and even though I wanted to try ligatures I couldn’t be bothered to “run a low quality fork”. Ghostty seems like the opposite of “low quality” and it renders Iosevka’s ligatures very well: My configured ligatures of Iosevka, rendered in Ghostty. Overall I feel that the font rendering in Ghostty is a little better than in alacritty, although that might be recency bias. I’m still undecided on ligatures but I love that I don’t have to feel limited by the terminal. I use a custom Iosevka build with these Ghostty settings: font-family = IosevkaTreeLig Nerd Font font-style = Medium font-style-bold = Bold font-style-italic = Medium Italic font-style-bold-italic = Bold Italic font-size = 16 Colorscheme While Ghostty has an absolutely excellent theme selector with a bunch of included themes (ghostty +list-themes) melange-nvim wasn’t included, so I had to configure the colorscheme myself. It was fairly straightforward even though the palette = 0= syntax was a bit surprising: # The dark variant of melange background = #292522 foreground = #ECE1D7 palette = 0=#867462 palette = 1=#D47766 palette = 2=#85B695 palette = 3=#EBC06D palette = 4=#A3A9CE palette = 5=#CF9BC2 palette = 6=#89B3B6 palette = 7=#ECE1D7 palette = 8=#34302C palette = 9=#BD8183 palette = 10=#78997A palette = 11=#E49B5D palette = 12=#7F91B2 palette = 13=#B380B0 palette = 14=#7B9695 palette = 15=#C1A78E # I think it's nice to colorize the selection too selection-background = #403a36 selection-foreground = #c1a78e I’m happy with Ghostty In the end Ghostty has improved my setup and I’m happy I took time to try it out. It took a little more time than “just launch it” but it absolutely wasn’t a big deal. The reward was a few pleasant improvements that have improved my life a little. And perhaps most important of all: I’m now an alpha Nerd that uses a terminal written in Zig. Did I create a custom highlighter for the Ghostty configuration file just to have proper syntax highlighting for this one blog post? You bet I did. (It’s a simple treesitter grammar.)

a month ago 45 votes
2024 in review

It’s time for my 15th yearly review. Nerdy things I enjoyed I read a lot of fantasy books this year! My favorite new series were The Kingkiller Chronicle, Gentlemen Bastards series, and The Stormlight Archive. If you’re curious about Sanderson’s books but a little apprehensive about jumping into a massive series such as The Stormlight Archive then I’ll recommend The Emperor’s Soul as an excellent little introduction. The standalone book Warbreaker is also fantastic (available for free on Brandon’s website). Customizing Neovim was fun and rewarding. It’s amazing I got anything productive done this year… I really enjoy working with Rust in my own hobby projects. Types are coming to Elixir and I’m loving it. (I recently migrated some small projects to v1.18 and found a bunch of errors.) The Gleam programming language shows a lot of promise. My one gripe is the pain of manually encoding/decoding JSON (even with the various libraries). Compared to for example Elixir dynamic encoding or Rust’s #[derive(Deserialize)] it just feels so bad that I’ve avoided Gleam for some projects. Shame on me? CSS is alive and better than ever. Things I accomplished I quit my job and started my own company. At the moment I’m focusing on consulting but maybe something else can grow from it one day? I wrote 26 blog posts—it was quite a productive blogging year for me. I built a custom keyboard together with a custom keyboard layout. Made the eBook for Why Cryptocurrencies? freely available and finally finished the How I wrote ‘Why Cryptocurrencies?’ series. I wrote a Tree-sitter grammar for Djot. I need to be more active maintaining it… But it’s hard to get motivated as I’ve got so many other interesting things I’d like to work on. Managing an open source project is not for the faint of heart (or the easily distracted). Finished the blog series about building my first 3D printer. I’m up to over 2100 printing hours with the machine so it’s safe to say I’ve been using it, not only playing around with. Rewrote my lighting home automation from Python to Elixir. I realized that meta-blogging is a great way to get virtual points on Hacker News. Tentative plans/goals/wishes for 2025 For some reason the idea of writing a fantasy novel got stuck in my head. I had a stint where I listened to dozens of hours of advice for aspiring writers and started planning a series. The excitement tapered off a bit during the Christmas holidays and I don’t know if this was just a temporary sidetrack or if it’s something I’ll actually end up doing. Design a one-handed keyboard layout. Again, this was just something my brain got stuck thinking about and I’m not sure if it’s just a fleeting idea or something I need to do so I can stop thinking about it. (Sometimes just a little planning plus solving the most difficult problems are enough—I don’t have to finish all the crazy/dumb ideas I get for my mind to consider them “done”.) Complete my second 3D printer. There’s no point in having a single printer; what if I break it and I can no longer print replacement parts for it? Develop my home automation system more. I’ve got a ton of things I’d like to improve (or play around with). For instance, yesterday I received the Home Assistant Voice Preview Edition that I hope works as well as advertised.

a month ago 40 votes
A type checking error in Elixir 1.18

Although I’m a big Elixir fan, the lack of static typing has always been my biggest annoyance (and why I think Gleam is so cool). I think static typing helps catch bugs earlier and in an automated way, leading to less buggy software and saves time in the long run. To my great joy Elixir is working on a new type system that will hopefully give us the early type checking errors I’ve been craving for. The system has been rolled out in steps since v1.17 and when I migrated to v1.18 I found my first type checking warning that I wanted to highlight. Comparison with structs This is the offending code with the corresponding warning: def get_surrounding_events_as_dt(events, now = %DateTime{}) do time = DateTime.to_time(now) next_i = Enum.find_index(events, fn {_, event_time} -> time < event_time end) || 0 warning: comparison with structs found: time given types: dynamic(%Time{}) where "event_time" was given the type: # type: dynamic() # from: lib/haex/sun.ex {_, event_time} where "time" was given the type: # type: dynamic(%Time{}) # from: lib/haex/sun.ex:88:10 time = DateTime.to_time(now) Comparison operators (>, =, Comparing with a struct won't give meaningful results. Structs that can be compared typically define a compare/2 function within their modules that can be used for semantic comparison. typing violation found at: │ │ next_i = Enum.find_index(events, fn {_, event_time} -> time │ ~ (The type checker cannot yet resolve event_time to the Time struct, leaving it as dynamic() in the text above.) The issue here as that < isn’t overloaded for the Time struct (like it would be in for instance Rust) and will instead perform structural comparison. You should use Time.before? instead of < (and DateTime.before for DateTime etc). As it happens for Time this doesn’t seem to be an issue as the structure happens to perform the comparisons in the same order as Time.before?, which this test verifies: test "check_times" do times = Enum.zip([0..23, 0..59, 0..59]) |> Enum.map(fn {h, m, s} -> Time.new!(h, m, s) end) for a <- times do for b <- times do assert a < b == Time.before?(a, b) end end end This is not the case for DateTime, which did cause a production bug in my home automation system, that my spouse complained about… Remember this when you think about types: type checking saves relationships. My hope for the future I’ve always disliked matching against atoms in Elixir as it’s so easy to make a mistake, for example like this: case Supervisor.start_child(supervisor, child_spec) do {:error, {:already_stated, pid}} -> Logger.info("Got pid: #{inspect(pid)}") (There’s a missing r in :already_stated.) At the moment this doesn’t produce an error but I really hope we’ll reach this point sooner rather than later as I make these kinds of mistakes all the time. I think I catch most of these with tests but I’m sure some slip through. I hope this isn’t that far away as the v1.18 type checker manages to catch a simpler case like this: def num_to_descr(num) do case num do 1 -> :one 2 -> :two _ -> :many end end def print(num) do case num_to_descr(num) do :zero -> IO.puts("zero") x -> IO.puts("Other: #{x}") end end warning: the following clause will never match: :zero because it attempts to match on the result of: num_to_descr(num) which has type: dynamic(:many or :one or :two) typing violation found at: │ 41 │ :zero -> IO.puts("zero") │ ~~~~~~~~~~~~~~~~~~~~~~~~

a month ago 44 votes

More in technology

Software engineering job openings hit five-year low?

There are 35% fewer software developer job listings on Indeed today, than five years ago. Compared to other industries, job listings for software engineers grew much more in 2021-2022, but have declined much faster since. A look into possible reasons for this, and what could come next.

3 hours ago 2 votes
400 million people use OpenAI/ChatGPT every week

Kate Rooney for CNBC: OpenAI Tops 400 Million Users Despite DeepSeek’s Emergence The San Francisco-based tech company had 400 million weekly active users as of February, up 33% from 300 million in December, the company’s chief operating officer, Brad Lightcap, told CNBC. I don’t

7 hours ago 2 votes
Introducing TagVault Surface Aero for AirTag

With the popularity of our TagVault Surface Mount for AirTag, we wanted another option that was just as durable, waterproof, and secure - but with a more minimal industrial design.  So we designed TagVault Surface Aero. It will look great on your motorcycle and even more discrete.  Mounts in seconds with strong 3M adhesive.   IP68 waterproof, with a new patent pending hidden gasket.   Sleek lines with an ultra low-profile   It's the best one time insurance you can buy.    Also available on Amazon: https://amzn.to/3EMsQ4c

4 hours ago 1 votes
Superhuman’s next big update looks very compelling

On the Superhuman blog: The Next Evolution of Superhuman AI 💖 Custom Auto Labels. Our built-in Auto Labels are great, but what's even better is making your own. Just write a prompt, like “job applications” or “requests for me to review work”. You can

4 hours ago 1 votes
Just Stop Oil is doing more harm for the cause than good

Mitigating climate change requires more than poems and protest

13 hours ago 1 votes