chubot 3 days ago

Congrats to the fish team! Great writeup with lots of interesting detail.

I wonder if this is the biggest project that has moved from C++ entirely to Rust (or maybe even C to Rust?) It probably has useful lessons for other projects.

If I'm reading this right, it looks like fish was not released as a hybrid C++ / Rust program, with the autocxx-generated bindings. There was a release during that time, but it says "fish 3.7 remains a C++ program" [1]

It sounds like they could have released if they wanted to, but there was a last stage of testing that didn't happen until the end.

Some people didn't quite get the motivation for adding C++ features to Rust [2], and vice versa, to enable inter-op. But perhaps this is a good case study.

It would be nice if you could just write new Rust code in a C++ codebase, without writing/generating bindings, and then throwing them away, which is mentioned in this post.

---

Also the #1 gripe with Rust seems to be that it supports version detection, not feature detection.

But feature detection is better for distros, web browsers, and compilers:

Feature Detection Is Better than Version Detection - https://github.com/oils-for-unix/oils/wiki/Feature-Detection...

Version/name detection is why Chrome and IE pretend to be Mozilla, and why Clang pretends to be GCC. Feature detection (e.g. ./configure and eval() ) doesn't cause this problem!

[1] https://github.com/fish-shell/fish-shell/releases

[2] e.g. https://news.ycombinator.com/from?site=safecpp.org

  • ComputerGuru 3 days ago

    To clarify, work on the rust rewrite started after 3.7.0, but the C++ code remained in a working branch on the git repo. Midway through the rewrite, we backported additions and improvements to fish scripts (most observable being new and improved completions) and a couple of important bugfixes from the rust-containing `master` branch to the C++ branch and released that as 3.7.1.

    We never considered releasing anything with a hybrid codebase; aside from the philosophical purity of fully making the switch to rust, it would have been a complete distribution nightmare (we take package maintainer requirements very seriously). Moreover, the code itself was not in a very pretty state - the port was very much like trying to undo a knot: you had to make it much uglier in order to get it properly undone. There were proverbial tons of SLoC that were introduced only for transitional interop purposes that were later removed, this code was never held to the same quality standards (in terms of maintainability; it was still intended to be bug-free and required to pass all our unit and integration tests, however).

    As mentioned in the article, we prefer to do feature detection when and where needed/possible. The old codebase was purely feature-detected via the CMake build system but we ended up writing our own feature detection crate for rust invoked via build.rs (maintained here [0]) though we just defer to libc on a lot (which doesn't do that yet). One side effect of the libc issue is that we're beholden to their minimum supported targets (though I'm not sure if that's strictly the case if we don't use the specific apis that cause that restriction?), which are higher than what we would have liked because we were fine with feature detecting and implementing using both older and newer apis where needed.

    [0]: https://github.com/mqudsi/rsconf

  • boris 3 days ago

    > Feature Detection Is Better than Version Detection

    The problem with feature detection (normally referred to as configuration probing), at least the way it's done in ./configure and similar, is that it relies on compiling and potentially linking (and sometimes even running, which doesn't work when cross-compiling) of a test program and then assuming that if compilation/linking fails, then the feature is not available.

    But the compilation/linking can fail for a myriad of other reasons: misconfigured toolchain, bug in test, etc. For example, there were a bunch of recent threads on this website where both GCC and Clang stopped accepting certain invalid C constructs which in turn broke a bunch of ./configure tests. And "broke" doesn't mean you get an error, it means your build now thinks the latest Fedora and Ubuntu all of a sudden don't have strlen().

    • ComputerGuru 3 days ago

      IMHO a broken toolchain is a broken toolchain and that's kind of outside the scope of autoconf -- and I say this despite having banged my head against the wall only too many times as a result of an odd toolchain misconfiguration leading me into chasing autoconf gremlins.

      One thing about rust is that it has always treated cross-compiling as a first-class citizen. Cargo is very intentional about the difference between the HOST and TARGET triplets and you can't mix them up unless you are doing so intentionally.

      The rsconf feature detection crate was similarly designed with cross-compilation in mind from the start and eschews running binaries in favor of some clever hacks to exfiltrate values during the cross-compilation process.

      There is only one rsconf feature (retrieving compile-time constants) that is currently labeled caveat emptor as it does not support cross-compilation; perhaps I can nerdsnipe someone here into figuring out a workaround: https://github.com/mqudsi/rsconf/issues/3

    • sunshowers 3 days ago

      I generally think autoconf etc should be defined to expect certain things by default (keyed by OS), and fail loudly rather than auto-disabling those features. If you really don't want those features, pass in --disable-foo.

      I re-did Firefox's autoconf to do this back around 2010 (was contracting for Mozilla as a part-time job in college), after running into one too many features that were automatically disabled because of a missing library. There was at least one Firefox nightly that was missing an important feature because the build machine didn't have the required library.

      • ziml77 2 days ago

        Yes! Please fail if a feature tells me its on by default but it can't be enabled for whatever reason. Otherwise I need to hope that, among all the output of the configure script, I didn't miss anything about the script choosing to disable a feature.

    • chubot 3 days ago

      Hm what's an example of those invalid C constructs? I'd be interested in seeing what happened

      One answer is the __has_feature tests mentioned in a sibling comment. Then you are using a supported API, not arbitrary code. Browsers should probably support something like that, if they don't already.

      But the arbitrary code is still a useful fallback, for when the platform itself doesn't support config probing

      I think you're saying that "writing good ./configure is hard", which is absolutely true. But it's still true that feature detection is better than version detection.

  • Conscat 3 days ago

    Although Clang does set the `__GNUC__` macro and you have to distinguish it using the `__clang__` macro, Clang and GCC also both have very fine-grained feature detection features as well, both at the CLI level and in the preprocessor (such as the `__has_feature` family of builtins).

scop 3 days ago

I remember switching from bash to zsh a few years back and thinking I was the bees knees. After the switch trying other shells seemed like bike-shedding because, I mean, what more could a shell? Then I got a new computer and decided to start from scratch with my tooling and downloaded fish. I was shocked how it instantly made zsh feel cumbersome and ancient.

Heartily recommend others give it a try as a daily driver for a couple of weeks. I liken it to Sublime Text: an excellent “out of the box” tool. Just the right amount of features, with the option to add more if you want. But you also don’t feel like your missing out if you keep it bare bones. A great tool in and of itself.

  • kstrauser 3 days ago

    Same here. I used it for about 3 days before I installed it on all my systems and permanently switched. For me, it was like the first time I learned a non-Latin language, and my eyes were opened to how much stuff I took for granted was completely arbitrary.

    For example, here's how you write an autoloaded function "foo" in Fish: you make a file called "foo.fish" in its config directory. Inside that, you write "function foo ..." to implement it. There's no step 3. That's it.

    Want to customize your shell prompt? Follow the process above to write a function called "fish_prompt" that uses normal scripting things like echo, pwd, git, or whatever to write your prompt to the screen. There's no step 2. That's it.

    Fish was revelatory. Other shells of the same vintage feel hopelessly outdated to me now. For context, I was the maintainer of FreeBSD's "bash-completion" port for a few years way back when. It's not that I don't have experience with other shells. I have plenty. I just don't want to use any of the others now.

    • sundarurfriend 3 days ago

      This was more convincing to me than the GP comment, especially the shell prompt part.

    • coffeeindex 3 days ago

      Is the “foo.fish” name required? Could I have “bar.fish” with “function foo…” inside and still autoload function foo?

      • ComputerGuru 3 days ago

        Not autoload, no. You can have as many functions as you want in a single .fish file, but it'll only be lazily autoloaded if it has the same name as the command you are trying to execute. It's how we avoid doing the I/O of scanning all fish directories and parsing their contents at startup.

        • PittleyDunkin 3 days ago

          ...and you can still explicitly source the files if you want to load the functions elsewhere.

  • pzmarzly 3 days ago

    Interesting, I went the other way about 7 years ago - switched from fish to zsh (initially with oh-my-zsh). The interactive experience was similar enough on both shells, and the performance was great on fish and okay-ish on zsh, but two things won me over:

    1. With zsh, I can copy-paste some bash snippet and in 99% of cases it will just work. Aside of copy-pasting from StackExchange, I also know a lot of bash syntax by heart by now, and can write some clever one-liners. With zsh, I didn't need to learn everything from scratch. (I guess this matters less now that you can ask AI to convert a bash one-liner into fish one-liner?)

    2. For standalone scripts... well, I think it's best to reach for a proper programming language (e.g. Python) instead of any shell language, but if I had to use one, I would pick bash. Sure, it has many footguns, but I know them pretty well. And fish language is also not ideal - e.g. IIRC it doesn't have an equivalent of `set -e`, you have to add `; or return 1` to each line.

    • WD-42 3 days ago

      I use fish and on the very, very rare occasion I need to copy and paste bash from the internet it's pretty easy to just type 'bash' into fish and paste it in. Its not like bash and fish conflict, you can have them both installed.

    • ComputerGuru 3 days ago

      FWIW, fish is much more bash-compatible these days. We've introduced support for a lot of bash-isms that don't completely break the fish spirit or clash with its syntax in the last few releases.

      • poincaredisk 3 days ago

        I personally liked "; and" but... "&&" solves around half of the problems with copy-pasting and does not look terrible, so it was probably the right thing to add.

    • kadoban 3 days ago

      > 2. For standalone scripts... well, I think it's best to reach for a proper programming language (e.g. Python) instead of any shell language, but if I had to use one, I would pick bash. Sure, it has many footguns, but I know them pretty well. And fish language is also not ideal - e.g. IIRC it doesn't have an equivalent of `set -e`, you have to add `; or return 1` to each line.

      I'm sure you know this, but: no particular reason the interactive shell you use has to match the shell you use for scripts. All of my scripts are in bash, but I haven't used bash interactively in decades now, at least on purpose.

      • johnthuss 3 days ago

        I write all my scripts with the hash bang as "#! /bin/bash" so even though fish is my interactive shell, I still use bash for all shell scripts. I think the restrictions you mention only apply if you use "#! /bin/sh" rather than bash specifically.

        • ComputerGuru 3 days ago

          Just fyi, you should use `#!/usr/bin/env bash` instead of `#!/bin/bash` or whatever because you can't assume the location of bash (but the location of `env` is indeed portably fixed). e.g. FreeBSD (and macOS?) has bash at `/usr/local/bin/bash`

          • carlhjerpe 3 days ago

            And NixOS has bash somewhere in the Nix store... :)

            Clarification: /usr/bin/env should be used for pretty much every shebang since it looks up the binary on $PATH.

          • massysett 3 days ago

            That assumes you care about portability. Not everybody does.

            Writing portable software is difficult, and doing it for shell scripts even more so. Blindly pursuing portability for its own sake is not worth it. Weigh the cost of portability against the odds that the software will ever run on different systems.

            For me personally it is never worth it to write my personal programs portably. This would require that I test them on different systems that I do not even use. Pointless.

            • mplanchard 3 days ago

              It’s not so much a portability thing IMO as it is a utility thing. If I have a newer bash in my PATH than what is in /bin/bash, I want to use it.

          • saagarjha 3 days ago

            bash is /bin/bash on macOS, unless the user really likes bash, in which case it's probably /opt/homebrew/bin/bash or /opt/local/bin/bash

            • pxc 2 days ago

              I wouldn't say I particularly like bash, bash has seen a ton of improvements since Apple stopped updating the vendored version. Using that old bash which is frozen for non-technical reasons just seems stupid to me.

              If you don't want bash-specific features, you might as well use zsh or dash or whatever lives in /bin/sh. If you do want bash-specific features, you might as well take advantage of the latest and greatest.

              On that note, on my Macs, the bash I want is usually /opt/pkg/bin/bash or /run/current-system/sw/bin/bash :)

            • mplanchard 3 days ago

              In any of those cases, using `/usr/bin/env bash` gets what the user probably wants

              • saagarjha 2 days ago

                Yeah I'm just commenting on what the path for that would be

          • zazaulola 3 days ago

            I'm confirming. Often, when you run a script on more than just your own computer, bash is located in unexpected places.

            For me, for example: `/data/data/com.termux/files/usr/bin/bash`

            In such cases, scripts containing the absolute path to bash in shebang do not run correctly.

    • jorvi 3 days ago

      I “devolved” mostly along the same path. Bespoke shell to OMZSH to Zsh to Bash.

      Zsh has a few nasty Bashism footgun incompatibilities. If I remember correctly the worst one is with how globbing / “*” works, which is why that is guarded with an option.

      My main reason for sticking with Bash is that it’s everywhere, and the places where it isn’t try very hard to support the most-used featureset of Bash.

      A stock Bash shell does feel a little naked without my dotfiles though :)

      • rat87 3 days ago

        Bash on osx is pretty old due to avoiding GPLv3. I think they have zsh as the default login shell

        • cpach 2 days ago

          True. But it’s easy to install Bash 5 via Homebrew or MacPorts.

    • wzdd 3 days ago

      Reading the associated issue (https://github.com/fish-shell/fish-shell/issues/510) about the lack of "set -e" was interesting as it highlighted how weird Bash, and shell scripting in general, is from a programming language perspective. Imagine programming in any other environment where every function you call could either succeed or fail catastrophically. There's some talk about adding exception handling to Fish, but maybe the sensible thing to do is to have a mode where Fish ensures that you've dealt with each possible error before moving on. Which is what you would do anyway if you were invoking external programs from a non-shell language (like Python's subprocess.check_call).

      In any case the discussion in that issue made a convincing (to me) argument that if you're doing the sort of scripting for which "set -e" makes sense, which is most of it, you should be using Bash. That doesn't mean you need to use Bash interactively though, as others have pointed out.

      • masklinn 3 days ago

        > Imagine programming in any other environment where every function you call could either succeed or fail catastrophically

        There's not much to imagine since that's pretty much every other language?

        Sure you can recover with error handlers (sometimes[0]), but by default all of them will hard abort in case of exceptions.

        In our modern language landscape shells are very much the odd ones, where errors are completely silent by default and the thing just carries on oblivious that the world around it might be crumbling completely.

        [0]: https://doc.rust-lang.org/book/ch09-01-unrecoverable-errors-...

      • pcthrowaway 3 days ago

        > Imagine programming in any other environment where every function you call could either succeed or fail catastrophically

        Laughs in client-side JS.

        • pavlov 3 days ago

          Hmm? It’s not like a JavaScript exception crashes the entire browser tab.

          Client-side JS is event-driven. An unhandled exception stops processing for that event, but doesn’t block other events.

      • izietto 3 days ago

        But, scripting languages are not programming languages, scripting languages are made to run commands, and by default a script should halt if a command fails, at least in the CLI execution context. The problem is, scripting languages mix programming context and scripting context, so a condition written in the script shouldn't be treated as a CLI exit status. Anyway, I don't use fish for scripts just for the lack of exit on command error. That's essential while scripting.

    • amluto 3 days ago

      I think that oilshell is aimed at people like you. I’ve never used it, but their website does make some interesting points about how a shell ought to work and how this could be compatible with bash.

    • assbuttbuttass 3 days ago

      As a go programmer, "; or return" makes a lot of sense to me

  • thayne 3 days ago

    I went bash -> fish -> zsh.

    The main reason I switched is because zsh can (often) source bash scripts and can use bash completion scripts (usually), and I was tired of having to translate things from bash to fish. I also ran into a few things where something that was relatively easy to do in bash was impossible to do with fish. But that was years ago so maybe that is less of an issue now, and I don't remember exactly what it was.

    Having used zsh, I think a big advantage it has over fish is the completions. There are completions available for more programs for zsh, and the zsh completions are sometimes higher quality in zsh.

    But I do generally like the syntax, and good out of the box experience of fish. I wish it had a bash or even posix compatibility mode and more available completions.

    • izietto 3 days ago

      I can relate with your comment a few years ago, but later the situation drastically got better, while not perfect yet (i.e. I still need a custom autocomplete function for aws). You might want to give it a try now anyway.

    • mplanchard 3 days ago

      I used bash for ages, and never really saw what zsh offered in comparison: I would have had to customize it almost as much as bash, and it didn’t really give me anything new.

      Fish was so much better than either out of the box, and I still have done virtually no configuration other than setting it up to use my common starship prompt, which is supported in bash as well.

      I don’t understand personally the argument about not having bash syntax. If I want it, I just run `bash`.

      • lucasoshiro 3 days ago

        > I don’t understand personally the argument about not having bash syntax.

        Three main reasons:

        1. The Fish language is only useful only for somehow extend fish itself, so it is pointless to spend time learning and practicing it unless I'm writing something for me or other Fish users.

        2. Sometimes we need to copy and paste something to our shell. When using Fish I must remember to set variables with set, get the status code with $status instead of $?, use () instead of $() and so on, which is a unnecessary overhead

        3. Bash's syntax is a hell: sometimes we forget a space, an escape, use end or done when we need to use fi or esac and so on. I don't trust my Bash code, I type everything in the terminal to check if everything is ok. In Fish I just can't do that...

        > If I want it, I just run `bash`

        That's what I do for 2 and 3. But when I do that I don't have the nice features of Fish...

        I still love Fish, though.

  • BeetleB 3 days ago

    Also, do consider xonsh.[1]

    It's a Bash-like shell written in Python. It has significant overlap with the awesomeness of fish, and has the advantage of being able to write your shell scripts in a Python dialect. So if you know Python, the mental burden is much lower.

    On top of that, it's cross platform, since Python is. No WSL needed.

    I switched to it in 2018 and haven't looked back. Originally it was just because I wanted a better command prompt environment in Windows for work, but I liked it so much I switched to it in Linux as well.

    (And yes, you can type any Python statement right in the command prompt).

    [1] https://xon.sh/

  • junek 3 days ago

    I know it's a typo but this:

    > what more could a shell?

    Is quite good. It could almost be the tag line for fish shell.

  • bravura 3 days ago

    Do you mind sharing what you think are the killer features of fish?

    • matthewmc3 3 days ago

      Fish has a lot of features out of the box I find really useful:

      * Command auto suggestions as you type based on your history

      * History search (using up arrow) based on a partial command

      * Helpful completions and descriptions when you hit TAB

      * Muti-line command editing

      * Syntax highlighting

      You can get all those same features in Zsh by using plugins, but those features work out-of-the-box with Fish with zero configuration. Zsh is a bit of a pain to configure, and pretty anemic without plugins. Fish makes configuration optional because it works how you'd hope your shell would out of the box. Even though Zsh has those features as plugins, they're kinda janky, not well maintained, and often conflict with other plugins.

      Additionally, Fish also has:

      * Excellent built in commands (string, math, argparse)

      * Sane scripting (word parsing where you don't need to quote everything, etc)

      * Great documentation

      * A web-based configuration if you're into that sort of thing (it's a bit of a gimmick for beginners)

      The main reason I use Zsh (or Bash) at all is for POSIX/portability, or for when I can't install something else. But for an interactive shell on a machine I control, it's hard to compete with Fish for speed, features, and ease of use.

      • lucasoshiro 3 days ago

        Other two things: Fish has an amazing integration with Docker and Git. If you type:

        docker stop <TAB>

        it suggests the hashes of the containers. About Git, you can, for example, type:

        git checkout <TAB>

        and Fish will suggest the available commits and tags. If you start to type a string it will also suggest the hash of commits whose messages match the string.

        I know that zsh may do the same using plugins. But Fish have all of that by default without being bloated. I use Fish since 2018, never installed a plugin and never thought that something was extra in it

    • chabons 3 days ago

      For me, it's that the ergonomics are straightforward, and everything works out of the box. If I find myself on a new machine, just installing fish gives me an ergonomic setup without having to install too many additional tools or mess with configuration.

      • HKH2 3 days ago

        Also, fish_config is there if you want to make quick changes without having to look up syntax.

    • mattgreenrocks 3 days ago

      Being able to avoid OMZ and entire cargo cult of zsh configuration performance “hacks” that litter the internet.

      Really, not needing to pull in other people’s janky scripts because the built-in features work well is huge. I still configure fish and use a few scripts, but it’s the lack of the massive cottage industry that is the primary draw for me.

      Of course, many devs see that as a failing: “how could a shell do its job well without a thousand knobs to tweak?”

  • ramon156 3 days ago

    We had the exact same experience, still in love with fish!

  • giancarlostoro 3 days ago

    My only issue with Fish is when pasting things from the web that assume Bash, a lot of the time it just works, then now and then I get screwed. I don't know nearly enough Fish or Bash to switch. Still though, I prefer Fish ultimately.

    • mplanchard 3 days ago

      It’s interesting how many folks in the comments have essentially this complaint, of not being able to paste bash from the internet. I just run `bash`, paste the thing, and then exit bash.

    • mekster 2 days ago

      People don't realize they don't have to stick to a single shell for both scripting and terminal use.

      I use zsh with plugins which pretty much makes it act like fish's convenience but one can use fish as their shell scripting while keeping the "bash" compatibility by keep using zsh or bash under terminal.

freedomben 3 days ago

> The one platform we care about a bit that it does not currently seem to have enough support for is Cygwin, which is sad, but we have to make a cut somewhere.

> We’re also losing Cygwin as a supported platform for the time being, because there is no Rust target for Cygwin and so no way to build binaries targeting it. We hope that this situation changes in future, but we had also hoped it would improve during the almost two years of the port. For now, the only way to run fish on Windows is to use WSL.

I understand, but this is indeed incredibly sad. To this day I still use Cygwin, and in fact prefer it to WSL depending on what I'm doing. Cygwin is an incredible project that is borderline miraculous for what it accomplished and provides. Without Cygwin I may not have any sanity left. I can't exude enough love for the Cygwin team.

Hopefully rust will support cygwin as a build target in the future!

  • anonnon 3 days ago

    It's strange how the article starts off complaining about C++'s platform "issues":

    > We’ve experienced some pain with C++. In short:

    > tools and compiler/platform differences

    before conceding that, because of Rust, they 1) are actually dropping support for a platform they previously supported and 2) can only support (in theory) a small fraction of those platforms supported by g++, but that that's OK because those are the only platforms which really matter. I get that it's a trade-off, but it would have been more intellectually honest to just admit this is one area (portability, backwards compatibility, and ABI stability) where C++ mops the floor with Rust, instead of pretending it's a another paintpoint Rust avoids.

    • mymoomin 3 days ago

      I don't see how the article is pretending anything. They had platform issues with C++ (portability and usability on the platforms they supported), and switching to Rust fixed those issues but gave them a different set of platform issues (they could no longer support Cygwin).

    • thayne 3 days ago

      Neither c++ nor rust is a clear winner in portability and platform support. C++ is available on more platforms, but in some ways rust makes it easier to support multiple platforms than it is in c++, for example using rustup to install the latest version of the compiler.

      What they got from this isn't that they can now support more platforms, but that they now don't have to spend as much effort on supporting dealing with differences between different platforms.

      • anonnon 3 days ago

        > Neither c++ nor rust is a clear winner in portability

        C++ is the clear winner in portability because of GCC and the wealth of platforms it supports. You can argue you don't care about supporting, e.g., OpenBSD on PPC, but trying to hand-wave away this advantage C++ has over Rust is disingenuous.

        • mst 3 days ago

          C++ is the clear winner in what portability is possible.

          But as they outlined, in a lot of cases achieving it is substantially more effort per arch+OS+version target than Rust.

          Getting a better ROI on your time is a valid reason to consider something better for your use cases.

        • whytevuhuni 3 days ago

          It's not disingenuous, you just missed this part:

          > but in some ways rust makes it easier to support multiple platforms than it is in c++

          The ease of installing Rust on Windows has helped build a culture of cross-platform libraries/crates, and so it's significantly easier to build applications that support more platforms than C++.

          Take a library for coloring text on a console, and chances are, it'll work on cmd.exe too (despite that not even using ANSI escape codes).

          Take a library for loading other libraries, and it will load .so, .dll, and .dylib too, with feature-gated methods to deal with each platform's quirks.

          Rust's standard library helps a bit, e.g. it isolates platform-specific modules into things like std::os::unix and std::os::windows, so it's a bit more obvious when you're trying to use something that won't work on all platforms.

          However, it's more just a cultural thing; many Rust things work cross-platform now, people see how nice that is, and so people try to maintain the status quo.

          With C++, you often need MSYS or Cygwin, and those have their own limitations; you can certainly make something in C++ that won't need them, it's just harder in comparison.

        • thayne 3 days ago

          > but trying to hand-wave away this advantage C++ has over Rust is disingenuous.

          I'm not trying to hand wave that away. That is an advantage c++ has. But if you only care about supporting platforms that rust supports, rust can make supporting all the platforms you do care about easier than if you used c++.

    • IshKebab 3 days ago

      C++ may run in more places than Rust but that's nothing to do with how good the tooling is. C++ runs everywhere AND its tooling is abysmal.

    • aragilar 3 days ago

      Yeah, it's somewhat interesting that they point to Debian's popcon (which is opt-in), when the statistics are basically coming from amd64, whereas I think it would be much more interesting (if possible) to see what the number of installs of fish are on openwrt (and other embedded distros). Currently the openwrt fish install is ~2MB (which is massive on a router), I wonder what the new install size will be with the rust version, and if practically they've dropped everything except desktop/server linux and MacOS?

      • ComputerGuru 3 days ago

        Rust binaries, once stripped, are not necessarily much fatter than their C++ counterparts. We're not expecting a huge increase there.

        Embedded distros should still be supported, though you might need to cross-compile for a few depending on rust toolchain availability. Cygwin is supposed to be getting a working rust target at some point, but who knows?

        • aragilar 3 days ago

          I fully expect fish 4.0 to be in openwrt (because openwrt runs on x86_64), but what percentage openwrt machines have the space to run it would be interesting (I suspect it won't be an issue, as likely those near the lower limit of openwrt are probably sticking with busybox anyway, and not installing a different shell).

          Personally, what I want is inexpensive hardware (routers, but also storage devices) that don't use much power (e.g. ~5W) but are also viable targets for projects like fish, so we can all have nice things.

          • ComputerGuru 3 days ago

            I know rust-fish is being used on at least some non-x86_64 non-aarch64 routers because we've accepted patches by those users to make it build on platforms without native 64-bit CAS.

            • tialaramex 3 days ago

              IIUC lacking 64-bit CAS is an example of a place where on the surface the Rust situation looks worse than C++ but that's misleading

              In this scenario C++ will provide "atomic" types that are just locking - they work but they don't have the behaviour you presumably wanted - and Rust will say OK, there's no 64-bit CAS so you can't have these features.

              If all you actually needed was a type that has apparently atomic behaviour then I guess the C++ feature is perfect, but I'm assuming almost nobody asks for an atomic type if they would have accepted a locked type instead and so for them Rust saying "No, sorry" is actually a good heads up that they need to think again for this target.

              • ComputerGuru 2 days ago

                Interesting perspective. In our case, we accepted a patch to effectively use a lock around a 64-bit integer as the workaround for these platforms, however.

            • saagarjha 3 days ago

              That would be any pre-ARMv8.1 machine?

              • ComputerGuru 3 days ago

                In this case, it was specifically openwrt on mipsel.

  • bloppe 3 days ago

    genuinely curious: with so much love for cygwin, why not just run Linux? possibly with a dual boot?

    • 3eb7988a1663 3 days ago

      Corporate jobs are nearly always on Windows machines. Cygwin+GitBash can usually sneak past the gate without raising too many eyebrows. WSL is still voodoo dark mark that can require conversations to get IT to allow.

      • freedomben 3 days ago

        Exactly. I have been running Linux on my personal computer for 15 years now. But frequently for work purposes and corporate jobs I have to work on Windows.

    • oguz-ismail 3 days ago

      Switching between OSes is a hassle. Besides WSL already has all the loveable parts of Linux, there isn't much point in dual booting anymore

      • coffeeindex 3 days ago

        If you’re using WSL, why use Cygwin?

        • hylaride 3 days ago

          If you're at a very large corporation, Cygwin could have been approved decades ago, but WSL is still going through "auditing". WSL is still new enough that bureuocratic organizations haven't satisfied themselves enough that it can be secured or are just plain stubborn enough to not want the hassle.

          I refuse to work at large companies for this reason, but one company I worked for brought on a large American bank as a customer and their infosec terms for vendors essentially required their IT "standards" on us, which sucked as we were a Mac shop. It almost came to a head when all the developers were told they had to seek approval for upgrading their build tools.

        • oguz-ismail 3 days ago

          To avoid using cmd.exe/PowerShell for stuff that needs to run natively. For example, when I used Linux I'd use this very small program named darkhttpd for sharing files among my computers over WiFi; when I switched to Windows I compiled it on Cygwin and it worked just as fine.

epage 3 days ago

> The one goal of the port we did not succeed in was removing CMake.

> That’s because, while cargo is great at building things, it is very simplistic at installing them. Cargo wants everything in a few neat binaries, and that isn’t our use case. Fish has about 1200 .fish scripts (961 completions, 217 associated functions), as well as about 130 pages of documentation (as html and man pages), and the web-config tool and the man page generator (both written in python).

Our issue for this is https://github.com/rust-lang/cargo/issues/2729

Personally, I lean away from Cargo expanding into these use cases and prefer another tool being implemented on top. I've written more about this at https://epage.github.io/blog/2023/08/are-we-gui-build-yet/

  • sunshowers 3 days ago

    (hi Ed!)

    I would definitely love to see Cargo have the ability to do this -- it means that `cargo install --locked` stays as a viable approach. It probably won't apply to fish, but I think being able to run a post-install command from the binary you just installed would suffice for my needs.

    • ComputerGuru 3 days ago

      We've actually added support to make single-binary fish deployments possible by (optionally) bundling static resources that would be part of the CMake-based deployment into the binary itself and having it unwrap those on first execution. The limitations of Cargo and the idiomatic `cargo install` usage primarily motivated this.

      • gorset 3 days ago

        I'm a big fan of this solution! It's always been annoying to perform all the ceremony involved in deploying a system with a bunch of files, with config, scripts and system written in a bunch of different languages.

        In my current project I just wrote the installer and config generation as part of the main method. Gets rid of a lot of complexity, with a simpler build, and is arguably easier to maintain. Single language, single binary.

      • sunshowers 3 days ago

        Ah interesting, I looked through your build.rs for the "installable" feature, and it looked like you were running sphinx-build in there. Do you plan to ship those artifacts in the .crate file?

qalmakka 3 days ago

As a decade-long user and as a professional C++ developer, I'm so happy they've managed to successfully port the shell to Rust. While I have a lot of fun writing C++ (and Rust), I must admit that Rust is vastly nicer to use.

People can complain as much as they want about the borrow checker, but you basically have to be as strict as Rust is in C++ if you want to really avoid use-after-free issues, ... I've been writing "Rusty C++" since before Rust was a thing, because that's the only sane approach to memory safety. I'd rather have a program check that I don't fumble up instead of running sanitizers when things go awry (often years later). The best bug is a bug that can't happen at all.

Static analyzers are sadly too limited compared to what a borrow checker can do in my experience. Some bad stuff will always slip in in C/C++.

  • bad_username 2 days ago

    What is you "rusty C++"? The only thing I can think of is strict adherence to RAII.

Too 3 days ago

Surprised to see the line count go up so much, 56K LOC of C++ to 75K of Rust. The blog attributes it to rustfmt using less oneliners. Even so, i would believe that should be a small factor compared to the heaps of duplicate code you get from c++ header files and all the other syntax ergonomics rust gives you.

Is this typical for such a translation. They also mention addition of new features contributing to more code, how much of the addition was new features vs pure translation?

Would be interesting to see the line count of the c++ version if it was run through a formater with similar configuration.

  • pornel 3 days ago

    Rust is denser than C, but both Rust and C++ can work on similarly high level of abstraction.

    It may be just down to rustfmt. It really adds a lot of vertical sprawl. I personally can't stand how much rustfmt makes multi-line code explode.

    • metaltyphoon 3 days ago

      Default to 80 chars is a travesty IMO, 100 or 128 would be a much better place.

      • pornel 3 days ago

        rustfmt uses 100-char lines by default (and can be configured to fill more), but that's not the problem with it.

        The problem is that as soon as a whole statement doesn't fully fit on a single line, rustfmt switches from "horizontal" to "vertical" strategy. It then stops caring how much vertical space it takes, inserts line breaks as often as the style allows, and won't try to use the available line width.

        You end up with long runs of finely chopped lines that contain only a single variable or a single call (often with each argument on a separate line too), which looks like having a 20-char line length limit.

        It's either fully oneliner `foo().bar().baz()` or fully vertical

            foo()
            .bar()
            .baz();
        
        
        and you can't have anything in between. It will fight you if you put two calls on the same line.
        • Mawr 2 days ago

          Good, that is the correct way to format code.

          - There are only two strategies and the algorithm to choose between them is trivial for a human to compute. This makes for way better readability, you can reliably predict where the next call/argument is going to be positioned.

          - Refactoring becomes easier - moving an argument is now a simple `Line up` editor action.

          - Source control diffs become more stable across changes.

          ...but it's hard to see the benefits on trivially simple examples like the one you presented. Here's a reformatting I did [1] to illustrate this:

          Original:

                 ReturnType<SomeOther<S, TypeConstructor<Nested<S, T, U>, T>>, U, HmmLetsAdd<V, W>>
          
          Reformatted:

              ReturnType<
                  SomeOther<
                      S,
                      TypeConstructor<
                          Nested<S, T, U>,
                          T,
                      >,
                  >,
                  U,
                  HmmLetsAdd<V, W>,
              >
          
          Vertically verbose, yes, but that hardly matters. The reformatting gave the code visual structure that's made it easy to understand.

          [1]: https://news.ycombinator.com/item?id=40427723

          • pornel 2 days ago

            Quite the opposite — it blows up the diffs:

            You rename a method, now it's a few chars shorter/longer, and some 1-liner call sites can become completely rewritten to the vertical style or vice versa.

            You delete a single line, now the expression can fit under a threshold, and the whole block is spaghettified (especially terrible when deleting a struct field).

            You wrap code in an if{}, which could have been a clean whitespace-only change for the entire body, but the indentation affects rustfmt's char counts, and it will now force different formatting decisions all over the place.

            If you're changing an infallible method to a fallible one, you could have added error handling/fallback on separate lines, keeping changes to the happy path minimal – but not with rustfmt.

            For minimal diffs you'd want something with a slack like gofmt, but rustfmt completely overlooked what makes gofmt so great and widely acceptable, and is a misanthropic ruthless canonicalizer instead, which ruins lots of use-cases, including minimal diffs.

            Rustfmt's heuristics aren't simple. They're based on char counting of AST nodes, with multiple different limits for different node types, and crossing any threshold can trigger an avalanche of reformatting. There are more complex rules for closures and comments.

            These heuristics are a source of formatting inconsistencies, e.g. each match arm is evaluated independently. Even when all match arms contain the same code, they can be formatted wildly differently due to patterns/name lengths pushing different thresholds. Indentation and AST context can make the same expression look differently each time. Such problems largely don't exist in gofmt, so it's not a problem of code formatters, it's a problem of rustfmt specifically.

underdeserver 3 days ago

The tone in the "The Timeline" section seems apologetic:

> The initial PR had a timeline of “handwaving, half a year”. It was clear to all of us that it might very well be entirely off, and we’re not disappointed that it was.

I'm amazed that you estimated it at so little time originally, and I'm amazed you shipped it in full in just 2 years. Congrats!

  • runiq 3 days ago

    Absolutely. Staying within an order of magnitude for a project of this size is just really good eyeballing. :)

    • ComputerGuru 3 days ago

      It's actually not fair to judge this one way or the other at the two year mark.

      We technically removed the last C++ code from the core project in January 2024 (~a year ago), the last C++ code altogether (a test helper) in June 2024 (six months ago). We only decided to push out a release now because we've added enough new features (not counting the rewrite as a feature) to warrant a release.

      But at the same time, someone could argue that the current codebase is still far from being fully idiomatic rust, there are various C++-isms ranging from the use of UTF-32 (historical from the nature of std::wchar/std::wstring under *nix) to still passing around file descriptors rather than rust `File` objects (that will take a lot of rearchitecting to make mut-safe).

      Ultimately, a project is never "done" and we're not being paid at all let alone contingent upon completion of the port, so there's no real use in saying it took precisely this long or that long. We're releasing now because we want to, but I wouldn't tie the release cadence with the port timespan.

      • underdeserver 2 days ago

        There may not be use for you, but there's use for me, because I've been doing this for a while and I understand the scale and complexity of such a project, and to see you pulling it off in such a short time scale is impressive. I'm impressed.

        Makes me reconsider fish :)

      • estebank 3 days ago

        The UTF-32 thing was confusing me. It is mentioned in multiple places but never explicit if it was a temporary design decision to ease the transition, perfectly reasonable, or the design going forward in perpetuity, in which case I would love to understand why something like bstr (WTF-8 under the covers) doesn't fit the bill. I've gathered so far that it might be the former, but if it is the later I would still like to know more.

        • faho 3 days ago

          Fish has always used utf-32 codepoints stored in wchar_t, from the first git commit in 2005.

          Unfortunately it's pervasive throughout the entire codebase (which does a lot of string shuffling).

          So it's a historical mistake, but not something to be fixed in the same step as switching the implementation language.

          bstr was mentioned as a direction and is a possibility.

nasretdinov 3 days ago

Very nice too see Rust being used where it is actually appropriate! Hopefully Rust "easy" multi-threading will allow more parts of fish to be async, even though it's already much better in that regard than bash (or any other shell I've seen).

One weird thing I'd also like to see is more bash integration, as others pointed out that being their primary motivation against switching to fish full-time. My use case is mostly sourcing bashrc/bashevv, and theoretically it should be possible in fish if I understand correctly: you need to be able to import e.g. every new env variable that changed before and after sourcing a bash script via real bash.

gorgoiler 3 days ago

I try not to post unsubstantive comments here but I’m just so moved by this success that I have to say an enormous Congratulations!

memco 3 days ago

Thought for a second that this was a 4.0 release announcement but this is just about the rewrite in rust. Any fish users wanting release notes of what to look forward to can look here: https://fishshell.com/docs/4.0b1/relnotes.html. Glad the rewrite is helping the dev team make improvements, but I’m more excited for the actual new features (except the new alt-backspace behavior which I’m sure I’ll get used to).

WD-42 3 days ago

Congrats to the Fish team. The best shell just got better.

How about updating the project tagline to: "Finally, a shell for the 00s!"

  • ComputerGuru 3 days ago

    Thanks but one cannot be too ambitious like that! '00s would mean the end of zip drives, dealing with unstandardized flash drives flakier than the floppy disks of old, and supporting point-and-shoot digital cameras!

    • WD-42 3 days ago

      That’s true. Better to stick to the 90s where we are safe.

    • nasretdinov 3 days ago

      I guess the author meant "the shell for '000s", but that's too much to type

outlore 3 days ago

I am curious to ask others here, are there other low-config alternative tools like Fish that, looking back, now seem like a no brainer? Ghostty is a recent example, Helix seems like another. I’d love to know about other tools people are using that have improved or simplified their lives.

  • nindalf 3 days ago

    Agree with you on helix. I love it.

    Atuin for improved history search.

    Starship for an improved shell prompt.

    zoxide - better cd

    ripgrep - better grep

    just - a command runner. I put project specific commands/scripts in there so I don’t have to remember.

    All of these are indispensable for me.

    • ComputerGuru 3 days ago

      imho starship is really just eye candy for the shell; it's not necessarily an actually improved shell prompt if you're on a "modern" shell like fish (a shell for the '90s!) or if you've put effort into customizing your shell experience with any of the other shells.

      • nindalf 3 days ago

        I’m on zsh and it’s definitely an upgrade for me.

        I want to say though, great work on this migration! Really fantastic work that others can learn from when they try a similar migration.

    • jjice 3 days ago

      +2 for ripgrep. Modern PCRE regex with lighting speed.

      I run into so many issues trying to adapt the regex in my head (usually PCRE) into the older grep and egrep style.

    • lawn 3 days ago

      fd a better find is one I like.

    • outlore 2 days ago

      I use and love all of these, thanks for sharing

    • anthk 3 days ago

      CD is builtin, there's no better cd.

  • KetoManx64 3 days ago

    Chezmoi was a complete workflow changer for me. https://www.chezmoi.io/ Let's me manage/synchronize my configs between systems. It has built in variables and scripting support so you can ignore sections of files or specific sections of files on certain systems, write specific configs for specific systems based on hostname or OS. It's a bit of work to get an understanding of, but incredibly powerful once you do.

    Whenever I setup a new system now, I install chezmoi, clone my comfig repo and then initialize it and it uses the chezmoi scripts to automatically installs all my programs and copies in the needed config files.

    • outlore 2 days ago

      Nice, I’ve been using dotter, will have to check out chezmoi

  • jsx2 2 days ago

    fish instead of zsh, Helix instead of Vim (or Micro instead of Pico/nano), Typst instead of LaTeX

  • surajrmal 3 days ago

    fastmod is a better sed.

  • datadeft 3 days ago

    mise, uv, ruff, starship is my current list.

OptionOfT 3 days ago

> it is often better to use if cfg!(...) instead of #[cfg(...)] because code behind the latter is eliminated very early

My experience with this is the other way around, especially if you have crates tied to that feature.

The cfg! is a marco that compiles to true/false, so whatever is inside of the if guard needs to compile regardless.

E.g.:

Cargo.toml

    [features]
    default = []
    my_feature = ["deps:feature_dependency"]

    [dependencies]
    feature_dependency = "1.0.0"
And in code:

    if cfg!(feature = "my_feature") {
        feature_dependency::something::Something::invoke();
    }
This will fail if you compile without `my_feature`.
  • CGamesPlay 3 days ago

    That was the point. The paragraph is talking about how errors only show up in some configurations, leading to “works for me” behavior for some of the devs. When you can get away with cfg!, you are more confident that it will at least compile regardless of the config being checked.

  • dajonker 3 days ago

    I might be wrong but most optimizing compilers will treat "if false" and the following code as dead and remove it.

    • Filligree 3 days ago

      It will remove it, but not until after resolving symbols. If the branch-never-taken references a missing library then this will still error, which is the problem for a feature flag.

  • mplanchard 3 days ago

    Fairly sure you’re agreeing with what you quoted

petepete 3 days ago

Really happy to see this, such a mammoth effort by the team and everyone else involved.

I switched over from zsh about four years ago and my config went from several hundred lines to a handful with just one plugin (fzf.fish).

It just works how I expect it to and I can't imagine changing again any time soon.

Spoof7726 3 days ago

> Fish also uses threads for its award-winning (note to editor: find an actual award) autosuggestions and syntax highlighting, and one long-term project is to add concurrency to the language.

(note to editor: find an actual award)

  • syhol 3 days ago

    The two most popular zsh plugins are total clones of this at 31k and 20k gh stars respectively. Not an award but certainly an indication of its success.

    • saghm 3 days ago

      Having used zsh with those plugins for a while and not having used fish personally, I'll nominate them for "most desirable plugins to copy for your own shell to make it more user-friendly".

  • dwattttt 3 days ago

    Seriously, can someone find them an award? I think they've earned it.

    • psd1 3 days ago

      Achievement unlocked: Centurion! _get over 100 comments on hacker news_

akdor1154 3 days ago

I'd be really interested to hear from distro packagers how this is going - how amenable is rust-fish to being packaged following e.g. Debian guidelines?

  • ComputerGuru 3 days ago

    We took an incredible amount of care to consider the package maintainer requirements for our the most popular distributions using/distributing fish. One of our maintainers is very careful about letting us know when we're doing something that might upset distro packagers, and we're constantly letting package maintainer guidelines and requirements influence how we structure fish itself and which dependencies we pull in.

    • akdor1154 3 days ago

      Awesome - i guess i was trying to get at 'if upstreams co-operate, is it possible to package rust stuff nicely, or is it still a square peg/dpkg-shaped hole scenario?'. Sounds like the former, which is excellent.

      (Also thanks for putting so much work into maintaining fish - i have used it as a daily driver for years, and posts like TFA showing it's maintained so professionally impress me a lot!)

  • zanchey 3 days ago

    It's hopefully not too tricky - it can't be packaged as a crate using (say) debcargo, as the install path still requires CMake. The Debian experimental package changes are mostly about pulling in the right dependencies (including some internal mangling to support some policy choices).

abbefaria27 3 days ago

Amazing write up! Everyone at work is itching to try Rust, but I think what’s killing adoption is that it’s not very clear how to gradually transition a code base. We have a few million lines of C++, some of it written 25 years ago. A full rewrite is just out of the question, at best we could use it for new sections. This is super common in the c++ world, so it’s a pity that porting wasn’t a first class concern in rust considering C++ devs are the target audience. It sounds like it was a challenge even at 57k LOC. Congrats to the fish team though, great accomplishment!

LAC-Tech 3 days ago

I use the shell a lot every day, mainly bash and some ash (alpine).

Does something like fish make the experience a bit smoother? is it pretty easy to get into?

  • scottyeager 3 days ago

    To answer your first question specifically, yes. With fish you get substantial ergonomic improvements over bash and ash out of the box. There's also a very minimal learning curve since these features build on familiar idioms. There are some differences with fish as a language that take some getting used to, but bash is always one command away if needed for more complex stuff.

    It's absolutely worth a test drive to see if the features excite you. If the lack of bash familiarity is too much of a blocker, then zsh with plugins that provide the same features as fish might be worth a look too.

  • acheong08 3 days ago

    I have to ssh into different places quite frequently and keeping the zsh configuration synced was a pain. Fish had 95% of what I needed out of the box so rather than putting a ton of scripts in place, installing omz, plug-ins etc, I run a single install command.

  • ComputerGuru 3 days ago

    fish is intended to be beginner friendly, whether you're new to the commandline world or not. It's essentially configuration-free, so that's about as easy to get into as you might imagine.

    • kstrauser 3 days ago

      Side note: beginner friendly or not, I've been using various kinds of shells for several decades and I still find Fish delightful. It's friendly to beginners, but also very comfortable to old salts.

naurupatel 3 days ago

We're flush with new and awesome terminals lately, Ghostty public launch now a huge upgrade to fish.

I've tried Fish a few times but hard to migrate over from bash/zsh. Does anyone have tips on how to port over a bunch of aliases/scripts/etc. easily?

  • andrewshadura 3 days ago

    You don't need to port your scripts. Migrating aliases shouldn't be too difficult.

jsx2 2 days ago

It seems the upgrade to 4.0 isn't available from Homebrew yet (brew upgrade fish -> Warning: fish 3.7.1 already installed)

djoldman 3 days ago

> 57K Lines of C++ to 75K Lines of Rust

...

> A lot of the increase in line count can be explained by rustfmt’s formatting, as it likes to spread code out over multiple lines, like: ...

I wonder what the character count diff is?

  • ComputerGuru 3 days ago

    So the problem with character counts is that unless you put in an insane amount of effort to calculate it, you're not going to get "significant chars" but rather "bytes"

    That said, you asked so here's the result of the difference within the `src/` directories comparing 3.7.1 and 4.0 beta (so excluding docs, fish scripts, etc):

        > cd fish3/src; find . -type f -exec cat {} + | tr -d '[:space:]' | wc -c
        2172330
    
        > cd fish-shell/src; find . -type f -exec cat {} + | tr -d '[:space:]' | wc -c
        2207996
    
    
    That's an increase of 35,666 bytes, or just 1.6%

    If you don't exclude whitespace, the difference is just under +250k bytes (an 8% increase).

chris_wot 3 days ago

Wow, amazing!

I wonder how a conversion of a C++ project that makes extensive usage on ranges would go.

preisschild 3 days ago

I would love to use fish, but it seems there really isnt a oh-my-zsh equivalent.

I dont even need the OMZ prompt (i use starship for that), but the aliases from the kubectl and git plugins are just so great to have if you use kubectl and git often.

Other plugins (like colored-man-pages, fzf-tab and syntax-highlighting) are also nice.

Is there something like that for fish?

Oh-my-fish has some of those features, but it seems to be abandoned.

  • ComputerGuru 3 days ago

    Integration with 3rd party scripts and tools is often a single line in your config.fish, something like `foo --init-fish | source` or better yet, `command -q foo && foo --init-fish | source`

    We don't recommend oh-my-fish for various reasons, but I guess what's really missing is just a gallery.

    • chisquared 3 days ago

      > We don't recommend oh-my-fish for various reasons

      Care to elaborate a bit on those? Or is it the kind of thing that's impolite to discuss?

wellthisisgreat 3 days ago

Is fish better than Zsh?

  • assbuttbuttass 3 days ago

    It's definitely better out of the box, with no configuration. If you add a bunch of fancy plugins to zsh then they can be very similar

  • arp242 3 days ago

    Depends what you want; in general:

    Fish offers one behaviour out of the box with very little configurability, and that it's. If you like that behaviour then Fish is great. If you don't, then well, it's not so much.

    zsh on the other hand is very flexible and can be shaped in to more or less anything you like. Some people really like that sort of flexibility and configurability, others don't.

  • lucasoshiro 3 days ago

    It depends on what you consider "better". ZSH out of the box is not much more than Bash, while Fish has really nice features without any configuration. But I think that the ZSH community is more mature and ZSH is compatible with Bash syntax (while Fish has its own syntax).

    Just install it and see if it's for you.

  • SMP-UX 3 days ago

    It's 'easier' for some people but you lose GNU bash compatibility and it kinda underlines all of the issues with interactive only shell systems -- a lack of interoperability.

    It's honestly a non-issue in the current year to learn zsh or tcsh

    • ComputerGuru 3 days ago

      On the other hand, fish being a clean-room shell implementation not beholden to the baggage of legacy systems is immune to some crazy behaviors or vulnerabilities that other shells - including zsh - are prone to: https://yossarian.net/til/post/some-surprising-code-executio...

      Compatibility has also come a long way in recent releases; you should give it a try.

      • arp242 3 days ago

        They don't work in zsh; they're bash issues.

        • faho 3 days ago

          No, they work in zsh, with one extremely small change: The referenced variable needs to exist.

          Try this (tested with zsh 5.9 on archlinux):

              foo='PWD[$(echo hahaha >&2)0]+42'
              [[ "$foo" -eq 5 ]]
          
          In bash, this would also print "hahaha" with "a" (or any other possible variable name) instead of "PWD", that's why many think it doesn't work at all in zsh.

          I'm pretty sure zsh has an optimization where it skips the indexing if the variable doesn't exist, which happens to sometimes stop this. But since you can just reference variables like PWD, that you know exist, it's not really a security improvement.

      • SMP-UX 2 days ago

        I don't have a system capable of building rust applications so no thank you

msoad 3 days ago

I love fish and I’ve been a user for years. In the wake of AI, I am really interested in getting out of completes via a local tiny AI model

Does the fish team have any plans for integrating AI models for other completion?

  • ComputerGuru 3 days ago

    We ship fish with completions ollama and llm, maybe others. We don't have any plans to "integrate" AI into the actual codebase.

    • msoad 3 days ago

      I had no idea! Where can I find docs to set this up?

      • orf 3 days ago

        Take some agency for yourself.

        https://github.com/search?q=repo%3Afish-shell%2Ffish-shell%2...

        That agency includes interpreting the search results alongside the reply to your original comment.

        • msoad 2 days ago

          Your snobby message didn’t help. This is for completion of ollama cli tool itself. I did search and couldn’t find the docs. Maybe the person responding to me also not understanding what I want. I want to prompt a tiny model for completion

          • orf 2 days ago

            > Maybe the person responding to me also not understanding what I want

            By asking for the docs? If you found that file already then it’s clear they misunderstood what you are looking for, and also that what you are looking for doesn’t exist.

          • ComputerGuru 2 days ago

            You can do that in your own custom completion.

cute_boi 3 days ago

Congratulations. Rust is really a great language. I wrote a small rust web server and its been a year and it seems to work great on $5 vps without any issue.

apatheticonion 3 days ago

Can I `source` my custom .bash_profile file into Fish? Trying it out it doesn't seem to work

rmac 3 days ago

fish > zsh > bash > *

SMP-UX 3 days ago

[flagged]

  • titaniumtown 3 days ago

    meme language? seems you dont have much constructive to say :p

rsyring 3 days ago

[flagged]

  • progbits 3 days ago

    Well you are in luck because that is exactly what the article is about.

    ??

    • rsyring 3 days ago

      Ha! I was in a hurry and misread this as the 4.0 release notes.

  • nemosaltat 3 days ago

    Me too. I just keep watching the crustea-culting and wondering if I’m actually missing out.

    • ykl 3 days ago

      So read this article, which is about exactly this?...

      • nemosaltat 3 days ago

        Yes it is. I was on mobile definitely didn’t scroll far enough for the giant “Why Rust” where the TFA addresses my needless snark head on.

        > It’s tempting to try to sweep this under the rug because it feels gauche to say, but it’s actually important for a number of reasons.

        > For one, fish is a hobby project, and that means we want it to be fun for us.

oguz-ismail 3 days ago

Another rewrite? Hope it'll take off this time

eviks 3 days ago

> What would test -x say on Windows, which has no executable bit?

It would say whether the file extension is executable (part of pathext env variable)

  • pie_flavor 3 days ago

    I should think it says the same thing as on Linux, since there absolutely is an 'executable bit' (GENERIC_EXECUTE) in the ACL.