Windows pain (#336)
* blog: start on windows pain post Signed-off-by: Christine Dodrill <me@christine.website> * flags Signed-off-by: Christine Dodrill <me@christine.website> * more Signed-off-by: Christine Dodrill <me@christine.website> * yse Signed-off-by: Christine Dodrill <me@christine.website>
This commit is contained in:
parent
b10c097504
commit
08865c84b6
|
@ -0,0 +1,291 @@
|
||||||
|
---
|
||||||
|
title: "Development on Windows is Painful"
|
||||||
|
date: 2021-03-03
|
||||||
|
tags:
|
||||||
|
- windows
|
||||||
|
- vscode
|
||||||
|
- nix
|
||||||
|
- emacs
|
||||||
|
- rant
|
||||||
|
---
|
||||||
|
|
||||||
|
# Development on Windows is Painful
|
||||||
|
|
||||||
|
<big>SUBJECTIVITY WARNING</big>
|
||||||
|
|
||||||
|
This post contains opinions. They may differ from the opinions you hold, and
|
||||||
|
that's great. This post is not targeted at any individual person or
|
||||||
|
organization. This is a record of my frustration at trying to get Windows to do
|
||||||
|
what I consider "basic development tasks". Your experiences can and probably
|
||||||
|
will differ. As a reminder, I am speaking for myself, not any employer (past,
|
||||||
|
present and future). I am not trying to shit on anyone here or disregard the
|
||||||
|
contributions that people have made. This is coming from a place of passion for
|
||||||
|
the craft of computering.
|
||||||
|
|
||||||
|
With me using VR more and more [with my Quest 2 set up with
|
||||||
|
SteamVR](/blog/convoluted-vrchat-gchat-setup-2021-02-24), I've had to use
|
||||||
|
windows more on a regular basis. It seems that in order to use [Virtual
|
||||||
|
Desktop](https://www.vrdesktop.net), I **MUST** have Windows as the main OS on
|
||||||
|
my machine for this to work. Here is a record of my pain and suffering trying to
|
||||||
|
do what I consider "basic" development tasks.
|
||||||
|
|
||||||
|
## Text Editor
|
||||||
|
|
||||||
|
I am a tortured soul that literally thinks in terms of Vim motions. This allows
|
||||||
|
me to be mostly keyboard-only when I am deep into hacking at things, which
|
||||||
|
really helps maintain flow state because I do not need to move my hands or look
|
||||||
|
at anything but the input line right in front of me. Additionally, I have gotten
|
||||||
|
_very_ used to my Emacs setup, and specifically the subtle minutae of how it
|
||||||
|
handles its Vim emulation mode and all of the quirks involved.
|
||||||
|
|
||||||
|
I have tried to use my Emacs config on Windows (and barring the things that are
|
||||||
|
obviously impossible such as getting Nix to work with Windows) and have
|
||||||
|
concluded that it is a fantastic waste of my time to do this. There are just too
|
||||||
|
many things that have to be changed from my Linux/macOS config. That's okay, I
|
||||||
|
can just use [VSCode](https://code.visualstudio.com) like a bunch of apologists
|
||||||
|
have been egging me into right? It's worked pretty great for doing work stuff on
|
||||||
|
NixOS, so it should probably be fine on Windows, right?
|
||||||
|
|
||||||
|
### Vim Emulation
|
||||||
|
|
||||||
|
So let's try opening VSCode and activating the Vim plugin
|
||||||
|
[vscodevim](https://marketplace.visualstudio.com/items?itemName=vscodevim.vim).
|
||||||
|
I get that installed (and the gruvbox theme because I absolutely love the
|
||||||
|
Gruvbox aesthetics) and then open VSCode in a new folder. I can `:open` a new
|
||||||
|
file and then type something in it. Then I want to open another file split to
|
||||||
|
the left with `:vsplit`, so I press escape and type in `:vsplit bar.txt`.
|
||||||
|
Then I get a vsplit of the current buffer, not the new file that I actually
|
||||||
|
wanted. Now, this is probably a very niche thing that I am used to (even though
|
||||||
|
it works fine on vanilla vim and with evil-mode), and other people I have asked
|
||||||
|
about this apparently do not open new files like that (and one was surprised to
|
||||||
|
find out that worked at all); but this is a pretty heavily ingrained into my
|
||||||
|
muscle memory thing and it is frustrating. I have to retrain my decade old
|
||||||
|
buffer management muscle memory.
|
||||||
|
|
||||||
|
#### Whichwrap
|
||||||
|
|
||||||
|
Vim has a feature called whichwrap that lets you use the arrow keys at the
|
||||||
|
end/beginning of lines to go to the beginning/end of the next/previous line. I
|
||||||
|
had set this in my vim config [in November
|
||||||
|
2013](https://github.com/Xe/dotfiles/commit/d8301453c2b61846eea8305b9ed4b80f498f3838)
|
||||||
|
and promptly forgotten about it. This lead me to believe that this was Vim's
|
||||||
|
default behavior.
|
||||||
|
|
||||||
|
It apparently is not.
|
||||||
|
|
||||||
|
In order to fix this, I had to open the VSCode settings.json file and add the
|
||||||
|
following to it:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"vim.whichwrap": "h,l,<,>,[,]"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Annoying, but setting this made it work like I expected.
|
||||||
|
|
||||||
|
#### Kill Register != Clipboard
|
||||||
|
|
||||||
|
Vim has the concept of registers, which are basically named/unnamed places that
|
||||||
|
can be used like the clipboard in most desktop environments. In my Emacs config,
|
||||||
|
the clipboard and the kill register* are identical. If I yank a region of text
|
||||||
|
into the kill register, it's put into the clipboard. If I copy something into
|
||||||
|
the clipboard, it's automagically put into the kill register. It's really
|
||||||
|
convenient this way.
|
||||||
|
|
||||||
|
[*It's called the "kill register" here because the vim motions for manipulating
|
||||||
|
it are `y` to yank something into the kill register and `p` to put it into a
|
||||||
|
different part of the document. `d` and other motions like it also put the
|
||||||
|
things they remove into the kill register.](conversation://Mara/hacker)
|
||||||
|
|
||||||
|
vscodevim doesn't do this by default, however there is another setting that you
|
||||||
|
can use to do this:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"vim.useSystemClipboard": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
And then you can get the kill register to work like you'd expect.
|
||||||
|
|
||||||
|
### Load Order of Extensions
|
||||||
|
|
||||||
|
Emacs lets you control the load order of extensions. This can be useful to have
|
||||||
|
the project-local config extension load before the language support extension,
|
||||||
|
meaning that the right environment variables can be set before the language
|
||||||
|
server runs.
|
||||||
|
|
||||||
|
As far as I can tell you just can't configure this. For a work thing I've had to
|
||||||
|
resort to disabling the Go extension, reloading VSCode, waiting for the direnv
|
||||||
|
settings to kick in and re-enabling the Go extension. This would be _so much
|
||||||
|
easier_ if I could just say "hey you go after this is done", but apparently this
|
||||||
|
is not something VSCode lets you control. Please correct me if I am wrong.
|
||||||
|
|
||||||
|
## Development Tools
|
||||||
|
|
||||||
|
This is probably where I'm going to get a lot more pedantic than I was
|
||||||
|
previously. I'm used to [st](https://st.suckless.org) as my terminal emulator
|
||||||
|
and [fish](https://fishshell.com) as my shell. This is actually a _really nice_
|
||||||
|
combo in practice because st loads instantly and fish has some great features
|
||||||
|
like autocomplete based on shell history. Not to mention st allowing you to
|
||||||
|
directly select-to-copy and right-click to paste, which makes it even more
|
||||||
|
convenient to move text around quickly.
|
||||||
|
|
||||||
|
### Git
|
||||||
|
|
||||||
|
Git is not a part of the default development tooling setup. This was surprising.
|
||||||
|
When I installed Git manually from its website, I let it run and do its thing,
|
||||||
|
but then I realized it installed its own copy of bash, perl and coreutils. This
|
||||||
|
shouldn't have surprised me (a lot of Git's command line interface is written in
|
||||||
|
perl and shell scripts), but it was the 3rd copy of bash that I had installed on
|
||||||
|
the system.
|
||||||
|
|
||||||
|
As a NixOS user, this probably shouldn't have bothered me. On NixOS I currently
|
||||||
|
have at least 8 copies of bash correlating to various versions of my tower's
|
||||||
|
configuration. However, those copies are mostly there so that I can revert
|
||||||
|
changes and then be able to go back to an older system setup. This is 3 copies
|
||||||
|
of bash that are all in active use, but they don't really know about eachother
|
||||||
|
(and the programs that are using them are arguably correct in doing this really
|
||||||
|
defensively with their own versions of things so that there's less of a
|
||||||
|
compatibility tesseract).
|
||||||
|
|
||||||
|
Once I got it set up though, I was able to do git operations as normal. I was
|
||||||
|
also pleasantly surprised to find that ssh and more importantly ssh-keygen were
|
||||||
|
installed by default on Windows. That was really convenient and probably avoided
|
||||||
|
me having to install another copy of bash.
|
||||||
|
|
||||||
|
### Windows Terminal
|
||||||
|
|
||||||
|
Windows Terminal gets a lot of things very right and also gets a lot of things
|
||||||
|
very wrong. I was so happy to see that it had claimed it was mostly compatible
|
||||||
|
with xterm. My usual test for these things is to open a curses app that uses
|
||||||
|
the mouse (such as Weechat or terminal Emacs) and click on things. This usually
|
||||||
|
separates the wheat from the chaff when it comes to compatible terminal
|
||||||
|
emulators. I used the SSH key from before to log into my server, connected to my
|
||||||
|
long-standing tmux session and then clicked on a channel name in Weechat.
|
||||||
|
|
||||||
|
Nothing happened.
|
||||||
|
|
||||||
|
I clicked again to be sure, nothing happened.
|
||||||
|
|
||||||
|
I was really confused, then I started doing some digging and found [this GitHub
|
||||||
|
comment on the Windows Terminal
|
||||||
|
repo](https://github.com/microsoft/terminal/issues/376#issuecomment-759285574).
|
||||||
|
|
||||||
|
Okay, so the version of ssh that came with Windows is apparently too old. I can
|
||||||
|
understand that. When you bring something into the core system for things like
|
||||||
|
Windows you generally need to lock it at an older version so that you can be
|
||||||
|
sure that it says feature-compatible for years. This is not always the best life
|
||||||
|
decision, but it's one of the tradeoffs you have to make when you have long-term
|
||||||
|
support for things. It suggested I download a newer version of OpenSSH and tried
|
||||||
|
using that.
|
||||||
|
|
||||||
|
I downloaded the zipfile and I was greeted with a bunch of binaries in a folder
|
||||||
|
with no obvious instructions on how to install them. Okay, makes sense, it's a
|
||||||
|
core part of the system and this is probably how they get the binaries around to
|
||||||
|
slipstream them into other parts of the Windows image build. An earlier comment
|
||||||
|
in the thread suggested this was fixed with Windows Subsystem for Linux, so
|
||||||
|
let's give that a try.
|
||||||
|
|
||||||
|
### Windows Subsystem for Linux
|
||||||
|
|
||||||
|
Windows Subsystem for Linux is a technical marvel. It makes dealing with Windows
|
||||||
|
a lot easier. If only it didn't railroad you into Ubuntu in the process. Now
|
||||||
|
don't get me wrong, Ubuntu works. It's boring. If you need to do something on a
|
||||||
|
Linux system, nobody would get fired for suggesting Ubuntu. It just happens to
|
||||||
|
not be the distro I want.
|
||||||
|
|
||||||
|
However, I can ssh into my server with the Ubuntu VM and then I can click around
|
||||||
|
in Weechat to my heart's content. I can also do weird builds with Nix and it
|
||||||
|
just works. Neat.
|
||||||
|
|
||||||
|
I should probably figure out how hard it would be to get a NixOS-like
|
||||||
|
environment in WSL, but WSL can't run systemd so I've been kinda avoiding it.
|
||||||
|
Excising systemd from NixOS really defeats most of the point in my book. I may
|
||||||
|
end up installing Nix on Alpine or something. IDK.
|
||||||
|
|
||||||
|
### PowerShell
|
||||||
|
|
||||||
|
They say you can learn a lot about the design of a command line interface by
|
||||||
|
what commands are used to do things like change directory, list files in a
|
||||||
|
directory and download files from the internet. In PowerShell these are
|
||||||
|
`Get-ChildItem`, `Set-Location` and `Invoke-WebRequest`. However there are
|
||||||
|
aliases for `ls`, `dir`, `cd` and `wget` (these aliases aren't always
|
||||||
|
flag-compatible, so you may want to actually get used to doing things in the
|
||||||
|
PowerShell way if you end up doing anything overly fancy).
|
||||||
|
|
||||||
|
Another annoying thing was that pressing Control-D on an empty prompt didn't end up closing the session. In order to do this you need to edit your shell profile file:
|
||||||
|
|
||||||
|
```
|
||||||
|
PS C:\Users\xena> code $profile
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you add this to the .ps1 file:
|
||||||
|
|
||||||
|
```
|
||||||
|
Set-PSReadlineOption -EditMode Emacs
|
||||||
|
```
|
||||||
|
|
||||||
|
Save this file then close and re-open PowerShell.
|
||||||
|
|
||||||
|
If this was your first time editing your PowerShell config (like it was for me)
|
||||||
|
you are going to have to mess with your
|
||||||
|
[execution policy](https://www.mssqltips.com/sqlservertip/2702/setting-the-powershell-execution-policy/)
|
||||||
|
to allow you to execute scrips on your local machine. I get the reason why they
|
||||||
|
did this, PowerShell has a lot of...well...power over the system. Doing this
|
||||||
|
must outright eliminate a lot of attack vectors without doing much on the
|
||||||
|
admin's side. But this applies to your shell profile too. So you are going to
|
||||||
|
need to make a choice as to what security level you want to have with PowerShell
|
||||||
|
scripts. I personally went with `RemoteSigned`.
|
||||||
|
|
||||||
|
### Themes
|
||||||
|
|
||||||
|
I use stuff cribbed from [oh my fish](https://github.com/oh-my-fish/oh-my-fish)
|
||||||
|
for my fish prompt. I googled "oh my powershell" and hoped I would get lucky
|
||||||
|
with finding some nice batteries-included tools.
|
||||||
|
[I got lucky](https://ohmyposh.dev/docs/installation/).
|
||||||
|
|
||||||
|
After looking through the options I saw a theme named `sorin` that looks like
|
||||||
|
this:
|
||||||
|
|
||||||
|
![the sorin theme in action](https://cdn.christine.website/file/christine-static/blog/Screenshot+2021-03-03+231114.png)
|
||||||
|
|
||||||
|
### Project-local Dependencies
|
||||||
|
|
||||||
|
To get this I'd need to do everything in WSL and use Nix. VSCode even has some
|
||||||
|
nice integration that makes this easy. I wish there was a more native option
|
||||||
|
though.
|
||||||
|
|
||||||
|
## Things Windows Gets Really Right
|
||||||
|
|
||||||
|
The big thing that Windows gets really right as a developer is backwards
|
||||||
|
compatibility. For better or worse I can install just about any program from
|
||||||
|
the last 30 years of released software targeting windows and it will Just Work.
|
||||||
|
|
||||||
|
All of the games that I play natively target windows, and I don't have to hack
|
||||||
|
at Steam's linux setup to get things like Sonic Adventure 2 working. All of the
|
||||||
|
VR stuff I want to do will Just Work. All of the games I download will Just
|
||||||
|
Work. I don't have to do the Proton rain dance. I don't have to play with GPU
|
||||||
|
driver paths. I don't have to disable my compositor to get Factorio to launch.
|
||||||
|
And most of all when I report a problem it's likely to actually be taken
|
||||||
|
seriously instead of moaned at because I run a distribution without `/usr/lib`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Overall, I think I can at least tolerate this development experience. It's not
|
||||||
|
really the most ideal setup, but it does work and I can get things done with it.
|
||||||
|
It makes me miss NixOS though. NixOS really does ruin your expectations of what
|
||||||
|
a desktop operating system should be. It leaves you with kind of impossible
|
||||||
|
standards, and it can be a bit hard to unlearn them.
|
||||||
|
|
||||||
|
A lot of the software I use is closed source proprietary software. I've tried to
|
||||||
|
fight that battle before. I've given up. When it works, Linux on the desktop is
|
||||||
|
a fantastic experience. Everything works together there. The system is a lot
|
||||||
|
more cohesive compared to the "download random programs and hope for the best"
|
||||||
|
strategy that you end up taking with Windows systems. It's hard to do the
|
||||||
|
"download random programs and hope for the best" strategy with Linux on the
|
||||||
|
desktop because there really isn't one Linux platform to target. There's 20 or
|
||||||
|
something. This is an advantage sometimes, but is a huge pain other times.
|
||||||
|
|
||||||
|
The conclusion here is that there is no conclusion.
|
|
@ -9,15 +9,14 @@ fn main() -> Result<()> {
|
||||||
.output()
|
.output()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
if std::env::var("out").is_err() {
|
let out = std::env::var("out").unwrap_or("/fake".into());
|
||||||
println!("cargo:rustc-env=out=/yolo");
|
println!("cargo:rustc-env=out={}", out);
|
||||||
}
|
|
||||||
|
|
||||||
let git_hash = String::from_utf8(output.stdout).unwrap();
|
let git_hash = String::from_utf8(output.stdout).unwrap();
|
||||||
println!(
|
println!(
|
||||||
"cargo:rustc-env=GITHUB_SHA={}",
|
"cargo:rustc-env=GITHUB_SHA={}",
|
||||||
if git_hash.as_str() == "" {
|
if git_hash.as_str() == "" {
|
||||||
env!("out").into()
|
out.into()
|
||||||
} else {
|
} else {
|
||||||
git_hash
|
git_hash
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue