Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
150626 stories
·
33 followers

Google Zero is under investigation by the EU

1 Share

Google is under investigation by the European Union over concerns that it breached competition rules by imposing restrictions on web publishers and YouTube creators to gain an unfair advantage over other AI companies.

Concerns outlined by the European Commission include using content from web publishers for features like AI Overviews and AI Mode in Search, and feeding YouTube content into Google's generative AI models - all while failing to provide "appropriate compensation" or the ability to refuse such use of their content. These concerns are tied to the existential threat of "Google Zero" - the moment in which Google Search no longer re …

Read the full story at The Verge.

Read the whole story
alvinashcraft
17 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

The rise of the 'hamster wheel.' The many names of Santa Claus. Unattractive turtles.

1 Share

1140. This week, we look at the difference between the modern phrase "hamster wheel" and the older "rat race," and why the former gained popularity. We also look at the similar concept of the hedonic treadmill. Then, we look at the many names for Santa Claus, including the Dutch "Sinter Klaas" and the German "Christkindlein."

The Santa Claus segment originally appeared on The Conversation and was written by Valerie Fridland, a professor of linguistics at the University of Nevada in Reno and the author of "Like Literally, Dude: Arguing for the Good in Bad English." You can find her at valeriefridland.com.

🔗 Share your familect recording in Speakpipe or by leaving a voicemail at 833-214-GIRL (833-214-4475)

🔗 Watch my LinkedIn Learning writing courses.

🔗 Subscribe to the newsletter.

🔗 Take our advertising survey

🔗 Get the edited transcript.

🔗 Get Grammar Girl books

🔗 Join GrammarpaloozaGet ad-free and bonus episodes at Apple Podcasts or SubtextLearn more about the difference

| HOST: Mignon Fogarty

| Grammar Girl is part of the Quick and Dirty Tips podcast network.

  • Audio Engineer: Dan Feierabend
  • Director of Podcast: Holly Hutchings
  • Advertising Operations Specialist: Morgan Christianson
  • Marketing and Video: Nat Hoopes, Rebekah Sebastian

| Theme music by Catherine Rannus.

| Grammar Girl Social Media: YouTubeTikTokFacebook. ThreadsInstagramLinkedInMastodonBluesky.


Hosted by Simplecast, an AdsWizz company. See pcm.adswizz.com for information about our collection and use of personal data for advertising.





Download audio: https://dts.podtrac.com/redirect.mp3/media.blubrry.com/grammargirl/stitcher.simplecastaudio.com/e7b2fc84-d82d-4b4d-980c-6414facd80c3/episodes/e1687bac-5ff1-4bb2-a46d-0229c36556c4/audio/128/default.mp3?aid=rss_feed&awCollectionId=e7b2fc84-d82d-4b4d-980c-6414facd80c3&awEpisodeId=e1687bac-5ff1-4bb2-a46d-0229c36556c4&feed=XcH2p3Ah
Read the whole story
alvinashcraft
18 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Dynamic data-driven scrollable button menu construction kit for Snap Spectacles part 1 - usage

1 Share

If you have played with my Spectacles lens HoloATC you might have noticed the start menu with a scrollable list of buttons, which allows you to choose airports. This is a dynamic menu, that gets its data by downloading it from a service on Microsoft Azure. A list of data is dynamically translated into a scrollable list of buttons. I have turned that into a reusable and extendable component - well, more like a construction kit - that you can plug into your own lens for use.

This will be a two part blog post. This first post is relatively short and explains how to use it, the next one will describe more in detail how it works. If just you want to use it, this post should get you going.

How does it look?

Well, like this.

menu

And if you press buttons, you see per button two messages in the logger:

loggeroutput

Both the button and the menu itself print out what button is pressed. That is all for now - it’s yours to decide what you actually want the events to do. The menu is a just frame, also stays neatly in view, but that’s all standard Spectacles Interaction Kit components. The only thing I added is a custom close button.

How can it be used?

Very fast and high over:

  • Make a prefab with a UIKit BaseButton, and make sure is has a BaseUIKitScrollButtonController component (or a child class of that)
  • Drag the ScrollMenu’s prefab onto the scene
  • Drag your button prefab on the input field “Scroll Button Prefab” of the ScrollMenu’s UIKitScrollMenuController component.
  • Create a bootstrapper script
  • Give that a reference (@input) to a UIKitScrollMenuController
  • Drag the ScrollMenu’s UIKitScrollMenuController on that input
  • The bootstrapper script somehow gets a feed of data, and turns in into a list of BaseScrollButtonData - or a list of BaseScrollButtonData child classes.
  • It feeds that list into UIKitScrollMenuController.createButtons
  • And the buttons will be created.

Now if that went a bit too fast, I will go over it into more detail

Button and button controller

The UIKitScrollMenuController, which I will talk about later, instatiates buttons within its scroll list, so it needs something to instatiate. If you look into the demo project, you will see an example of how such an instantiable button prefab might look. My example is called, very orignally, MyButton. This has a couple of rather standard components, and it also has a MyButtonController.

MyButton

It is defined like this:

import { BaseScrollButtonData } from "LocalJoost/Ui/ScrollWindow/Scripts/BaseScrollButtonData";
import { BaseUIKitScrollButtonController } 
  from "LocalJoost/Ui/ScrollWindow/Scripts/BaseUIKitScrollButtonController";

@component
export class MyButtonController extends BaseUIKitScrollButtonController {
    protected applyCustomSettings(scrollButtonData: BaseScrollButtonData): void {
        super.applyCustomSettings(scrollButtonData);
        this.uiKitButton.onTriggerDown.add(() => {
            print("From MyButtonController: button pressed: " + scrollButtonData.buttonText);
        });
    }
}

Your button controller must inherit BaseUIKitScrollButtonController. It inherits a Text and a UIKitButton @input field from it, and those must be set in the editor. The base class does a lot of useful things, setting the button text amongst others. It also gives you an applyCustomSettings method to override, in this case it rather trivially prints out to the logger that it is pressed, and shows the button text from the BaseScrollButtonData that it has been fed.

BaseScrollButtonData

This is a very simple data class from which buttons are created and every buttons gets fed such a BaseScrollButtonData object (or a child class)

export class BaseScrollButtonData {
    public buttonText: string;
}

As stated, you can also make a child class that contains lots more data fields, and do something interesting with it to the button in the override of applyCustomSettings of your custom equivalent of MyButtonController. For instance, you can add a color attribute and give every button a different color. Or, like I did, you can add attributes that hold location, altitude, name and the IATA airport code of an airport and use that to select a location on a map when a button is pressed.

Configure ScrollMenu prefab

The whole menu is fit within the ScrollMenu prefab. Drag this prefab onto your scene. The prefab has a couple of inputs you can fill, all of which can be ignored - apart from the Scroll Button Prefab input: that must contain a prefab. Drag your Button prefab on that field

scrollmenu

and the ScrollMenu is almost ready to go.

Feed the menu and listen to the menu

As wrote before, the menu needs a list of BaseScrollButtonData data objects containing at least the button text to be able to generate a list of buttons. This is a sample of a bootstrapper script that does just that:

import { BaseScrollButtonData } from "LocalJoost/Ui/ScrollWindow/Scripts/BaseScrollButtonData";
import { UIKitScrollMenuController } from "LocalJoost/Ui/ScrollWindow/Scripts/UIKitScrollMenuController";

@component
export class ScrollButtonDataLoader extends BaseScriptComponent {
    @input scrollMenuController: UIKitScrollMenuController

    private onAwake(): void {
        const buttonDataArray: BaseScrollButtonData[] = [];
        for (let i = 1; i <= 20; i++) {
            const buttonData = new BaseScrollButtonData();
            buttonData.buttonText = "Button " + i;
            buttonDataArray.push(buttonData); 
        }
        this.createButtons(buttonDataArray);
        this.scrollMenuController.onButtonPressed.add((data) => {
            print("From UIKitScrollMenuController: button Pressed: " + data.buttonText);
        });
    }
}

This script needs an reference to the menu’s UIKitScrollMenuController so in can call it’s method createButtons method.

In real use, buttonDataArray would be filled by reading a data stream from the web or some kind of configuration file. However, in this simple sample I just make them locally. But the scrollMenuController also exposes and event onButtonPressed to which you can subscribe and do something with, although here we also just print out the data that was fed to the button, just to show it works.

Some bits and pieces

The UIKitScrollMenuController also features a setMenuVisible method which you can use to turn the menu of or off from the outside, without having to reload the data using the ScrollButtonDataLoader or whatever you want to call your loader script.

Make sure your scripts lives in a scene object under the actual ScrollMenu prefab, otherwise you most likely will run into the dreaded “Compent not yet awake” error.

For the sake of completness: this menu needs both the Spectacles Interaction Kit and UIKit to be installed.

The demo project with all the neccesary components can be found here.

Read the whole story
alvinashcraft
18 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

It works on my cluster: a tale of two troubleshooters

1 Share

Kubernetes has a gift for making simple problems look complicated, and complicated problems look simple. When something breaks, you often see symptoms completely unrelated to the real cause of the problem. This leads to a problem I like to call “blaming the network team”, where problems end up being diagnosed by the wrong engineers for a given issue.

This is a real problem in the industry - not only for large enterprises, but also for smaller organizations that are transitioning from “Steve-based deployments”, where teams are learning to work separately yet still together.

I’ve personally experienced this dichotomy during my time as an engineer, working on both software and infrastructure, so I’m going to tell a story from two perspectives: the infrastructure engineer who initially looked at an issue, and the software engineer who was able to help solve the problem. It’s based on a real-world issue I experienced at a previous company I worked at, though I had much less fun solving it in real-time than writing this blog post.

I’ll discuss the tools used, the rabbit holes I dove into, and how I (eventually) learnt from our mistakes. Ultimately, discussing this will help others learn from my mistakes and enable teams to work together more effectively.

The backstory

The application that started it all is a GraphQL “gateway”. Written in Node.js, its job is to receive requests from clients, then connect to various backend services to retrieve data, stitch it together, and send it back. To say it’s in the critical path is an understatement - if it’s unhappy, so are customers.

One Thursday morning, it became very unhappy.

We started to receive reports from customers about timeouts and error messages. Our support team had a look at the issues they were seeing and immediately escalated to the infrastructure team - they were seeing strange errors:

Error: getaddrinfo EAI_AGAIN accounts.production.svc.cluster.local

The support team saw getaddrinfo, googled the problem, and quickly decided it was a DNS problem - time to page the infrastructure engineer!

Part 1: The Infrastructure Investigation

When you’re the infrastructure engineer and DNS errors appear, you need to move quickly. DNS is fundamental, especially in Kubernetes, where it’s often used in lieu of service discovery.

Starting With What You Know

First things first: are the CoreDNS pods actually running?

 kubectl get pods -n kube-system -l k8s-app=kube-dns

NAME                       READY   STATUS    RESTARTS   AGE
coredns-7c65d6cfc9-grq72   1/1     Running   0          2d20h
coredns-7c65d6cfc9-z5svs   1/1     Running   0          2d20h

All pods are running, with no restarts or changes since the issue started. Sweet - let’s check the logs.

 kubectl logs -n kube-system -l k8s-app=kube-dns --tail=100

.:53
[INFO] plugin/reload: Running configuration SHA512 = 591cf328cccc12bc490481273e738df59329c62c0b729d94e8b61db9961c2fa5f046dd37f1cf888b953814040d180f52594972691cd6ff41be96639138a43908
CoreDNS-1.11.3
linux/arm64, go1.21.11, a6338e9
.:53
[INFO] plugin/reload: Running configuration SHA512 = 591cf328cccc12bc490481273e738df59329c62c0b729d94e8b61db9961c2fa5f046dd37f1cf888b953814040d180f52594972691cd6ff41be96639138a43908
CoreDNS-1.11.3
linux/arm64, go1.21.11, a6338e9

The logs are empty, but at least there’s no errors!

If CoreDNS is healthy, it could be a general networking issue. We should quickly test from a fresh pod:

 kubectl run debug-dns --rm -it --image=busybox --restart=Never -- nslookup accounts.production.svc.cluster.local

Server:         10.96.0.10
Address:        10.96.0.10:53

Name:   accounts.production.svc.cluster.local
Address: 10.96.80.99

pod "debug-dns" deleted from production namespace

It works! DNS resolution is working, at least from a debug pod, but the error we’re seeing is definitely pointing to DNS timeouts.

Checking the Metrics

Perhaps it’s a capacity issue that only becomes apparent under load. Let’s look at the CoreDNS metrics:

Image of grafana, showing CoreDNS metrics that are normal

Everything seems normal, but just in case, let’s try scaling the coreDNS deployment:

 kubectl -n kube-system scale deployment coredns --replicas 3

deployment.apps/coredns scaled

After a few minutes, nothing has changed!

Let’s try with load

Everything indicates that DNS working fine, but the gateway is still failing. It could be due to the load on the DNS servers. To test the hypothesis, we load test the DNS servers:

kubectl run debug-dns --rm -it --image=busybox --restart=Never -- sh -c 'while true; do nslookup accounts.production.svc.cluster.local > /dev/null || (echo "failed" && break); done'

This pod simply ran nslookup until DNS failed, except it didn’t fail.

The Dead End

At this point, we’ve spent the entire morning verifying that the DNS infrastructure is completely healthy. CoreDNS was working, the network was working, and other pods were resolving DNS without any issues. However, the gateway continued to throw EAI_AGAIN errors.

The error message said DNS was broken. Every check said DNS was fine. At this point, we’re certain that something has changed in the software itself; it’s time to throw this issue over the wall to the software team responsible for the gateway.

Part 2: The Developer Investigation

Getting a visit from the infrastructure guy is rarely good news. “DNS is broken for your app, but I’ve investigated DNS, and it’s working fine!” is particularly bad news, though.

Checking the deployment history

Since DNS is working fine for everything else in the cluster, something must have changed to trigger this issue - perhaps there was a recent deployment? We’ll check in Octopus Deploy to see whether there’s been any changes:

A screenshot of Octopus Deploy, showing the deployment history

It looks like yesterday, your recent change made it through to production:

A screenshot of Octopus Deploy, showing the deployment timeline for production

You’re familiar with this change - it’s a small performance optimization that adds a local cache. Instead of fetching and parsing schemas from backend services on every request, the gateway cached it to disk to look up when a request comes through. This shouldn’t impact DNS at all! Let’s verify the manifest that was deployed:

Diff view, showing only changes to the image for the deployment

It’s only an image change - is it in sync in the cluster?

Live status view, showing in-sync resources

The resources all seem to be in sync, so they’re definitely unchanged.

Looking for patterns

Live status, showing logs from the problematic pod.

You can see the error logs with DNS issues in production, but when you examine your dev and test environments, none of them are showing the issue. In addition, you only see the DNS errors when there are lots of requests coming in at once. Maybe that’s why the issue isn’t showing up in the test environment!

Replication

To try and replicate the load of the production environment in the test environment, you boot up k6 and start generating GraphQL requests. As the load goes up, you wait to see DNS errors, but … nothing! All that happens is that the service slows down slightly, even at over 10 times the load that production is experiencing.

You’ve spent most of the afternoon trying to replicate the issue in the test environment, and still, nothing - it’s looking like we might need to start the complicated rollback process before the end of the day.

Part 3: Bridging the Gap

Before finishing up for the day, everyone catches up and discusses next steps. They go over the facts first:

  • The errors received are definitely related to DNS
  • No other pods are receiving DNS failures
  • There doesn’t seem to be networking issues
  • The DNS servers don’t seem to be having issues
  • The DNS failures seem to start when there’s lots of load
  • The same build of the software in test doesn’t have the problem, even when load tested
  • The only change made was to add caching

This leads the infrastructure engineer down the path of the differences between environments:

  • In test, there’s only 1 replica
  • In production, there’s 3 replicas
  • In test, the single replica uses an SSD volume
  • In production, the replicas use a shared disk

Maybe this is somehow related to the shared disk?

Following the Thread

A search for DNS errors Node.js Kubernetes file locks turned up a Medium article, along with a suggestion to bump the UV_THREADPOOL_SIZE to help fix DNS resolution problems. After more research, it turns out that when a file is locked and you attempt to read it (even asynchronously), one of 4 threads (by default) will be taken up, waiting for the file call to be returned. One other job of these threads is DNS resolution!

The developer quickly made a change to move the cache to memory and re-hydrate on launch. The infrastructure engineer made a change to the UV_THREADPOOL_SIZE environment variable to help resolve the issue while the fix rolled out, and the problem began to ease immediately.

The post-mortem

During the incident post-mortem, we ended up writing up what went wrong:

  1. Schema cache writes files to a shared volume on one pod
  2. Schema is attempted to be read/written by another pod
  3. Under high traffic, these operations deadlock
  4. The cache operations saturate the threadpool while waiting on locks
  5. dns.lookup() calls queue up waiting for a free thread
  6. Queued DNS lookups eventually timeout
  7. Application logs: EAI_AGAIN

In the end, even though the error was related to DNS, the actual problem was filesystem contention that only occurred when running in environments with multiple replicas.

Part 4: Looking to the future

Though finding this bug was painful for me at the time, it helped me to bring a new approach to troubleshooting failures, especially around distributed systems like Kubernetes with multiple layers of abstraction.

Involve developers early

Developers have the most context around what’s going on in their app - if something is going on, they’ll know the changes and usage patterns much more intimately than infrastructure teams. Ensure that developers have the necessary access to independently investigate.

Make sure deployment history is visible

When something breaks, “What changed?” should be the first question. Making it easy for both infrastructure and software teams to see the deployment history to environments is one of the best things you can do.

A list of deployments to separate environments

Document dependencies

Software tends to have the most problems in the seam between software and hardware - IO. When using networking, storage, or other IO, it’s worth documenting why and how you’re doing so. It helps infrastructure teams understand requirements, especially in distributed systems.

Automate rollbacks

A significant reason this bug affected people longer than we had hoped was due to the complicated and involved rollback process. One of the first things we did afterwards was create a runbook to automate the process of rolling back, so that we could mitigate the problem faster and buy time to investigate issues.

A runbook for automating the runbook procedure

Conclusion

When you’re troubleshooting in Kubernetes, you’re troubleshooting a system that spans multiple layers of abstraction, multiple teams, and multiple mental models. No matter what tools or processes you use, when you’re trying to solve a problem, allowing as many people as possible to contribute their understanding of the systems involved is the most important thing to do.

The next time you’re debugging an incident and discover DNS caused it, I hope you’ll remember this story about one of the rare instances when it wasn’t. Remember the lessons we learnt, so if the next issue isn’t DNS, you’ll be able to dig deeper and solve the problem with way less stress than we did.

Read the whole story
alvinashcraft
19 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Replit Introduces New AI Integrations for Multi-Model Development

1 Share

Replit has introduced Replit AI Integrations, a feature that lets users select third-party models directly inside the IDE and automatically generate the code needed to run inference.

By Daniel Dominguez
Read the whole story
alvinashcraft
19 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Trying out the Zed editor on Windows for .NET and Markdown

1 Share

In this post I provide my initial thoughts about the Zed editor. I provide my first impressions, some of the customizations I made to get comfortable with it, and my conclusions on using it for working with .NET and Markdown documents.

What's wrong with VS Code?

Before I get to my actual impressions, I think it's probably worth discussing why I started looking at the Zed editor in the first place. After all, I currently have JetBrains Rider, Visual Studio, and Visual Studio Code installed on my laptop, do I really need another one?😅

Of course, while you can use all these IDEs/editors for much of the same tasks, they have different sweet spots. For example, JetBrains Rider is my go-to IDE day to day. It's what I use for virtually all my "real" development these days. Visual Studio fills essentially the same role for me, and consequently I don't use it much, there's just occasional things where I find the deeper integration with Azure (among other things) come in handy.

And then we have VS Code. VS Code always used to be a quick, lightweight editor. It had good-enough general syntax highlighting for all sorts of arbitrary languages, the .NET integration was "good enough" when all I want to do is hack together a quick console app for a blog post, and it's actually a pretty good markdown editor. But VS Code has been starting to bug me more and more recently. It's nothing that I can really put my finger on, it's the little things…

First of all, and the main gripe to be honest, is that VS Code just doesn't feel as snappy as it used to. It's not terrible, but I go out of my way to try to not have too many extensions installed now, because it just exacerbates things. I want to be able to edit a file in explorer and have it pop up straight away, not to have to wait 5 seconds for the window to appear.

The other thing that bugs me recently is, ironically, the "improved .NET support", by way of the C# Dev Kit. And the experience that irritates me is the same irritating feature Visual Studio insists on: creating sln files all over the place. There's a perfectly good csproj in the folder, that's good enough! Stop creating pointless sln files!

Oh look, VS Code decided it would create a sln file for no good reason

Obviously I understand why it does this, but I literally never want this behaviour. I also don't care about the "solution explorer" window—if I need that view I'll use a real IDE like Rider. Why can't you just be happy as an editor, VS Code?!

I have some other more minor gripes, but as none of that's particularly productive, let's move on. One thing that I do enjoy about VS code is the markdown editing experience. I use the Markdown All in One extension, Spell Right, and Word Count, and it does everything I need.

So in conclusion I was feeling a bit down on VS Code as an editor. It was still better than anything I had used before, but it wasn't quite the darling that I had once considered it to be. And that's when a colleague at work mentioned they'd been using (and enjoying) Zed.

Maybe Zed can replace VS Code?

Zed is an editor I'd heard about a few times on the changelog podcast. It was interesting, as it was created by Nathan Sobo, a developer that previously worked on Atom at GitHub, but it went in a completely different direction. While Atom used Chromium and Node (and spawned the Electron framework so many apps use today), Zed was very different. It was built in Rust, and designed to be very fast.

Zed was interesting from an academic point of view, but not hugely practical for me, for several reasons:

  1. It didn't support Windows, (until recently)!
  2. A big sell is about being "collaborative", something I wasn't interested in for an editor.
  3. They've largely pivoted Zed to be an AI play, again something I'm not interested in for an editor.

But then, in October 2025, Zed released a Windows build. After a colleague at work told me how much they were enjoying it, I decided to give it a go, and see if it could replace VS Code for my day to day usages.

As a reminder, what I really wanted was and editor that:

  • Is fast.
  • Works well with Markdown
  • Works with small .NET projects (when opening an IDE is too slow!)

So I installed Zed onto my personal machine, and gave it a try!

Installing Zed for Windows

To install Zed, head to https://zed.dev/windows, and hit the download button (Or just press W!)

The Zed for Windows home page

This downloads the installer, which is your pretty standard affair, and it includes the usual options for adding Zed to the explorer context window for example (ideal for what I would be using it for).

The Zed installer Additional Tasks wizard, allowing you to register Zed in the Windows Explorer Shell

On running Zed for the first time, you're presented with some base customization options:

The customization options on the welcome screen of Zed

The ability to base your keymap on other well known editors and to import settings from other editors is a very neat onboarding trick. I chose to import my settings from VS Code:

The screen after importing settings from VS Code

Once you're done with the setup, you're dropped into the default welcome screen, which overall looks pretty similar to the VS Code experience. You have your getting started actions, an explanation of the shortcuts available, and a bunch of toolbars around the place:

The Zed start screen after first install

I tried generally just opening a few files at this point and looking around, typing a little bit, and I have to say, the first impression is very impressive. It's just so smooth and snappy. Seriously, it feels so fast compared to VS Code. It was a good start! 😄

Adding support for C# to Zed

Much like VS Code, Zed is built around various protocols, and delegates large parts of its core functionality to extensions. There are extensions for themes, extensions for icon packs, extensions for languages…the list goes on! You can open the extension window using the same shortcut as VS Code, Ctrl+Shift+X (at least, assuming you're using the VS Code shortcuts!)

The Zed extension window showing the extensions you can install

To add support for C#, open the extensions window, search for C#, and install the C# extension by fminkowski. This uses the omnisharp Language Server to provide language support. This is essentially the same backing implementation as the original VS Code C# extension, before Microsoft moved to the C# Dev Kit extension.

Once the extension is installed you get syntax highlighting for your C# code, as well as refactoring options, just as you would expect in VS Code, though these will likely be more limited than the options available as part of the VS Code C# Dev kit.

C# file in Zed showing a refactoring popup

That's the most important part of getting .NET editing working in Zed, but I also tweaked the themes to be more familiar. I installed the JetBrains Rider theme, and also the JetBrains New UI Icon Theme, though the latter didn't seem to have special icons for C# files, so that's a bit of a shame. Anyway, that's it for editing .NET for now; let's look at markdown instead.

Adding support for Markdown

The good news is that Zed has built-in support for Markdown, so there's nothing you need to install. That said, it's relatively pretty bare bones:

The markdown experience in Zed

You get syntax highlighting of the markdown text, and a preview pane, but there's not a huge number of other features (more on that later). For me, the one critical extension I added was a spell checker. I added CodeBook, which is actually intended to be used as a spell checker inside code rather than markdown, but it does work with markdown at least:

A markdown document with a flagged spelling mistake including suggestions.

But the question is, did I stick with it? Did I write this post in Zed?

My first impressions after trying Zed

The short answer is, no, I didn't stick with Zed, and instead went back to VS Code. There's a lot of reasons for that which I'll get into, but before I start nipicking, I think it's worth highlighting the good bits.

The good bits

Zed feels really smooth to use. It opens quickly, tabbing between documents is lighting fast, and even typing feels much faster than VS Code. Switching folders/workspaces is crazy fast😮 The performance is one of those things that you don't realise you're missing until you try it for yourself! 😀

Also, I was really impressed with the care that's clearly gone into building and designing Zed. In the relatively short time I used it, I ran into literally no bugs or issues, and the attempt to accommodate onboarding VS Code and other editor users was a really nice touch. Pretty much all of my reasons for not sticking with Zed were missing features rather than anything else.

So now let's talk about those missing features.

.NET is good, but missing Razor support

First, editing .NET, for the most part, just worked. I mean, it's like working in VS Code, which is basically all I wanted or needed. I'm not looking to replace Rider with Zed, so I don't need a full IDE.

The one piece that was missing is that there doesn't seem to be any support for Razor or cshtml files, which I think is an Omnisharp limitation. And if that's the case, it'll probably never be there unfortunately🙁

.razor files don't have any syntax highlighting

This isn't really a knock against Zed or the Omnisharp project; Razor is a notoriously difficult format to handle as it's multiple languages in one: HTML, C#, Blazor @ syntax, CSS, JavaScript etc. And it's not really a big deal for me; Zed is meant to be my editor and I'm generally not going to be messing with Razor pages in an editor.

So overall, Zed is "good enough" with .NET to be my go-to editor. Unfortunately, that's not the case for Markdown.

Markdown is missing too many features

After checking out .NET I was pretty optimistic with Zed, as I assumed that would be the hard bit, but unfortunately I was ultimately let down by the Markdown support.

Markdown has first-party support in Zed, but it's missing a lot of features that I'm used to having when writing in VS Code. Many of these are features provided by the extension I use, but they make for a very smooth writing experience:

  • Shortcuts like Ctrl+B to bold the current word. This has been requested for Zed, but doesn't currently exist.
  • "Code folding" for headings and other elements. These let you hide sections, just like you would when folding a method in code.
  • "IntelliSense" for internal links and for images (which are added via a shortcut of course!).
  • Images are rendered in the preview pane
  • As you scroll the source page (without moving the cursor), the preview window scrolls too.

However, the biggest issue with markdown is the way Zed constantly pops up suggestions for the word you're currently writing. This is incredibly distracting, provides no value when writing markdown documents, and frankly made it unusable for me.

The suggestion popups when writing Markdown in Zed are infuriating

These all seem like small things, and they are, but they add up to a slick experience, and importantly an experience I'm used to. I've been writing this blog for long enough now that it's just not worth throwing away nearly a decade of muscle memory😅

That said, most of these are small features that absolutely could be added later or addressed, so I'm certainly going to keep an eye on it.

A lot of shortcuts don't port across

On the theme of muscle memory, one of the big struggles I had initially was realising quite how many shortcuts I use instinctively. This can be very confusing when you hit a shortcut expecting it to (for example) create a new cursor on the line below, and instead it switches to a completely different document😅

None of this is a big problem, as you can customize basically all of the keyboard shortcuts. I'm also not entirely sure if these were just not mapped in the "import Keymaps from VS Code" stage, or if these aren't part of the "core" VS Code or something. Anyway, I've added the following mappings so far to get something closer to what I have in VS Code:

// Zed keymap
[
  {
    "context": "Workspace",
    "bindings": {
      // "shift shift": "file_finder::Toggle" 
    }
  },
  {
    "context": "Editor && vim_mode == insert",
    "bindings": {
      // "j k": "vim::NormalBefore"
    }
  },
  {
    "context": "Editor",
    "bindings": { "ctrl-shift-delete": "editor::DeleteLine" }
  },
  {
    "bindings": { "ctrl-d": "editor::DuplicateSelection" }
  },
  {
    "bindings": { "ctrl-k ctrl-f": "editor::FormatSelections" }
  },
  {
    "context": "Editor",
    "bindings": { "ctrl-k ctrl-d": "editor::Format" }
  },
  {
    "context": "Editor",
    "bindings": { "alt-enter": "editor::ToggleCodeActions" }
  },
  {
    "context": "Editor",
    "bindings": { "shift-f12": "editor::FindAllReferences" }
  },
  {
    "context": "Editor",
    "bindings": { "f3": [ "editor::SelectNext", { "replace_newest": false } ] }
  },
  {
    "context": "Editor",
    "bindings": { "shift-f3": [ "editor::SelectPrevious", { "replace_newest": false } ] }
  },
  {
    "context": "Editor",
    "bindings": { "ctrl-alt-down": "editor::AddSelectionBelow" }
  },
  {
    "context": "Editor",
    "bindings": { "ctrl-alt-up": "editor::AddSelectionAbove" }
  },
  {
    "context": "Workspace",
    "bindings": { "alt-s": "workspace::ToggleLeftDock" }
  },
  {
    "context": "Pane",
    "bindings": { "alt-left": "pane::GoBack" }
  },
  {
    "context": "Pane",
    "bindings": { "alt-right": "pane::GoForward" }
  },
  {
    "context": "Editor",
    "bindings": { "ctrl-k ctrl-c": [ "editor::ToggleComments", { "advance_downwards": false } ] }
  }
]

Which brings us to the final point.

The AI elephant in the room

As I already mentioned, I don't want or need AI in my editor. And yet every company has to add AI to their product whether you want it or not. Such is the way of our times. VS Code and Visual Studio are the same. But the good thing about Zed is that you can simply disable it if you don't want it:

You can disable AI in Zed if you don't want AI features

Alternatively you can edit all the settings as JSON. This is what I have currently:

// Zed settings
{
  "ensure_final_newline_on_save": false,
  "remove_trailing_whitespace_on_save": false,
  "format_on_save": "off",
  "when_closing_with_no_tabs": "keep_window_open",
  "disable_ai": true,
  "telemetry": {
    "diagnostics": true,
    "metrics": true
  },
  "project_panel": {
    "auto_fold_dirs": false
  },
  "base_keymap": "VSCode",
  "minimap": {
    "show": "never"
  },
  "file_types": {},
  "show_whitespaces": "trailing",
  "icon_theme": {
    "mode": "dark",
    "light": "Zed (Default)",
    "dark": "JetBrains New UI Icons (Dark)"
  },
  "ui_font_size": 13.0,
  "buffer_font_size": 12.0,
  "theme": {
    "mode": "dark",
    "light": "One Light",
    "dark": "JetBrains Rider Dark"
  }
}

And that's pretty much it. In conclusion, I won't be replacing VS Code with Zed today. But I can definitely see a time in the near future where enough of the missing markdown features I'm used to have been added that I'll make the switch. The Zed team are shipping updates regularly, and they have a really nice product, even if it's not quite there for me.

Summary

In this post I described my experience installing the Zed editor, and trying to replace my VS Code usages with Zed. In particular, I wanted to use Zed to edit .NET projects and to write markdown documents. The .NET experience was very similar to the VS Code experience with the Omnisharp plugin, which is mostly only lacking with regards to Razor/Blazor support. For Markdown I found the lack of features I'm used to in VS Code to be a deal breaker. Zed is an incredibly fast and smooth experience, but I won't be switching to it currently. If the features I'm missing are added however, I would seriously consider it.

Read the whole story
alvinashcraft
19 minutes ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories