Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fish configuration snippets are read prematurely because they are sourced from $__fish_datadir/config.fish #3918

Closed
therealpxc opened this issue Mar 26, 2017 · 12 comments
Labels

Comments

@therealpxc
Copy link

therealpxc commented Mar 26, 2017

My environment:

fish version:

fish, version 2.5.0

operating system:

Linux davetim 4.9.17 #1-NixOS SMP Wed Mar 22 11:44:07 UTC 2017 x86_64 GNU/Linux

According to the Fish documentation, user snippets ($XDG_CONFIG_HOME/fish/conf.d/*.fish) are supposed to be read after system-wide configuration files ($__sysconfdir/conf.d/*.fish). But they are sourced in $__fish_datadir/config.fish, which comes before $__fish_sysconfdir/config.fish.

On NixOS, this causes massive breakage, because until $__fish_sysconfdir/config.fish (generated by the operating system to set up all the correct paths and include admin-specified config for the operating system) has been sourced, external programs not required by fish itself (you can see the dependencies at the top of that file there) are not on the PATH and there are similar problems for other path-like variables— it's not just about executables. So on my system, for example, when ~/.config/fish/conf.d/omf.conf is sourced and loads up a fish plugin which depends on the program hostname, I get breakage, before I can even see my prompt. I don't just mean error messages either— I mean the whole console hangs and I have to switch to a new VC.

I've been able to work around this issue by making sure the first snippet loaded from my home directory sources /etc/fish/config.fish and that /etc/fish/config.fish exits early if it has already been sourced by a given shell.

The breakage for this is pretty damn pervasive, especially if your display manager runs from your login shell (like SDDM does). When I first encountered this bug, it both killed my display manager and rendered all of my virtual consoles unusable.

@krader1961
Copy link
Contributor

This was discussed in issue #3099 and the decision was made to leave it this way but to clarify the documentation.

@faho, in light of this issue is further discussion needed?

@krader1961 krader1961 added this to the fish-future milestone Mar 26, 2017
@faho
Copy link
Member

faho commented Mar 27, 2017

Nix is using the wrong file. /etc/fish/config.fish, like anything in /etc, is supposed to belong to the administrator.

There's a variety of things that nix can do, among them

  • Use share/__fish_build_paths.fish.in - which is sourced before any configuration file and can also include $PATH if you want

  • Use a snippet that is guaranteed to be first (like 00-nix.fish) in $__fish_datadir/vendor-conf.d

@Profpatsch: Care to comment on this? Any reason you're using $__fish_sysconfdir/config.fish here?

The reason I think this should be changed in Nix is that we want this sourcing order. We want config.fish to override snippets.

@faho
Copy link
Member

faho commented Mar 27, 2017

Just to be clear since my previous comment could be read as a bit grumpy:

I'm happy to help Nix here, but since I don't use it, I'm going to need to have my hand held a bit. Specifically, I'm going to need information on why the way we've envisioned this (__fish_build_paths.fish) isn't working (if it isn't, otherwise please just use that and then everyone's happy). Then I'm going to need information on what you need.

What I won't do is change the file precedence, since I strongly believe that what we have here is the right way of doing it. We read /usr/share/fish/config.fish first because that's an internal fish thing that just happens to be named "config". Then we read the snippets and then the administrator and user files so that both the administrator and user can override whatever the snippets (which could be included in packages or downloaded with OMF or fisherman or something) decide.

@therealpxc: You've stated in #3099 (comment):

I know having to implement this bit in the C++ code means generating more work for you

Implementing this in C++ wouldn't fix this since we'd want the same order.

And also

my Linux distro is kind of marginal and non-standard

Well, it is. But that would also apply to fish. And both are non-standard in interesting ways, which means I'm happy to help. You don't just demand shebang lines use %! instead or patch ed to print "WHAT" instead of "?". You're actually doing interesting stuff, and I'm interested in how it works out.

We've added stuff to help Haiku, so we can also add stuff to help Nix. But for that we need to know what to add.

@therealpxc
Copy link
Author

therealpxc commented Mar 27, 2017

Great! I'm appreciate your help and I look forward to a little back and forth about this. :-)

So there are two places where Nix/NixOS deals with fish: one is a module, which is an operating-system level configuration tool, and the other is simply a package for fish. In NixOS, the module is activated by the system administrator when they choose to add programs.fish.enable = true; to their config. So in this sense what we do with $__fish_sysconfdir/config.fish is done on behalf of the system administrator in order to enable fish as a login shell. And in the process of doing this, we also include administrator-specified config in the generated file. So it includes some stuff that's all about NixOS quirks, but it's in the same file where we incorporate administrator-provided config. You can see what the options look like, as an administrator might use them, in a nicer format here. If the administrator does not choose to enable fish as a login shell, I think it just inherits its environment from the shell that launches it, and none of that module code is read (which is why this bug affected NixOS users who chose fish for a login shell, not the Gentoo user who simply used the Nix-provided fish package).

This is also the only way to modify /etc/fish/config.fish in NixOS; in NixOS all of /etc are symlinks into read-only files in the /nix/store/<hash>-whatever/.... So in a sense we are still only writing to /etc/fish/config.fish when prompted by the administrator, on the administrator's behalf. But I think maybe we can still do a better job of separating OS-level concerns related simply to initializing fish altogether and other more particular administrator choices, and that could help solve our problem here.

Does that explanation of why /etc/fish/config.fish is involved make sense?

@therealpxc
Copy link
Author

So long as we end up with fish working right on NixOS, I'm of course happy with whatever load order is appropriate for fish on its own terms, so to speak. But I am curious about why the mode of overriding snippets previously described in the documentation (snippets of the same names override each other according to precedence which prefers user snippets to admin snippets and admin snippets to vendor snippets, if I read it correctly) is inadequate for allowing appropriate overriding.

Is it just that doing so is trickier, because you have to figure out which snippet is causing what and then write a snippet of the same name? I can understand wanting to avoid that.

@faho
Copy link
Member

faho commented Mar 27, 2017

a module, which is an operating-system level configuration tool

So if I'd install Nix I'd pick "the fish module" and "the KDE module" and "the firefox module" to end up with fish as my shell, KDE as my desktop and firefox as my browser?

And in the process of doing this, we also include administrator-specified config in the generated file.

So in that sense it's a configuration "wizard"? And if I understand Nix correctly this all ends up as part of the package, in the exact state the user picked?

But I think maybe we can still do a better job of separating OS-level concerns related simply to initializing fish altogether and other more particular administrator choices, and that could help solve our problem here.

Yes, it appears like it.

I am curious about why the mode of overriding snippets previously described in the documentation (snippets of the same names override each other according to precedence which prefers user snippets to admin snippets and admin snippets to vendor snippets, if I read it correctly) is inadequate for allowing appropriate overriding.

That actually still happens. Only we distinguish between "snippets" (which are files in the "conf.d" directories) and config.fish. All the config.fish should always be read (since you want those to be additive), but snippets have the precedence thing.

So the way it currently works:

  • /usr/share/fish/config.fish (which is really internal to fish and just happens to be named "config.fish")

  • All the snippets, with vendor < admin < user precedence and in natural order (the same ordering as globs, with "1" < "02")

  • /etc/fish/config.fish (for the administrator)

  • ~/.config/fish/config.fish (for the user)

The path to /usr/share/fish/config.fish is compiled in (as $__fish_datadir) and can be picked via ./configure. The path to the "vendor" snippets is read from $__fish_datadir/__fish_build_paths.fish, which is built from share/__fish_build_paths.fish.in via ./configure. This is also a full-fledged fish script that is simply sourced.


So, with that out of the way, here's what you want, from my understanding:

  • You want somewhere you can set $PATH (because that contains directories with the system-state-hash, like /nixstore/abcdeadbeef/ that change without fish changing).

  • This needs to be read before snippets are evaluated (because those want to run commands). Ideally we'd also guarantee that fish won't try executing a non-builtin before it is sourced.

  • You'll want to change it frequently (since it changes anytime any package changes)

and

  • You'll want to change it programatically without a full fish parser (so it shouldn't include anything else)

but:

  • It will only contain simple set VAR VALUE assignments, no fancy command substitutions or anything

and

  • It only needs to be read at shell startup, not monitored for changes

Is that correct?

Thinking about this, __fish_build_paths.fish would probably work for you (though we should read it earlier). I wouldn't recommend a custom snippet (because ordering is annoying there).

However: How are you doing this for other shells? We already read a variety of more-or-less system-specific configuration files (like systemd's locale.conf or OSX's /etc/paths), so we could also add one more.

What we would need for such a file though would be a guarantee that it sticks to a small subset of POSIX-sh, like a simple VAR=VALUE with optional quotes (that's pretty much the locale.conf format). We could read this with just builtins.

Am I making any sense?

@therealpxc
Copy link
Author

therealpxc commented Mar 27, 2017

Am I making any sense?

Yes, I think we're getting somewhere. :-)

So if I'd install Nix I'd pick "the fish module" and "the KDE module" and "the firefox module" to end up with fish as my shell, KDE as my desktop and firefox as my browser?

More or less. So Nix/NixOS kind of operates on two levels: one is a package manager (called Nix), which can be used atop other distros. The other level is NixOS, which is a whole distribution based upon the Nix package manager and other tools built around Nix-the-language, which is also used by the package manager which shares its name (the naming thing is kind of terrible, I know). So on my system, the relevant lines for those three things (all of which I use) are

services.xserver.desktopManager.plasma5.enable = true; # this uses a NixOS module to say ‘we gotta install KDE packages and do some setup’
programs.fish.enable = true; # this uses a NixOS module to say ‘we gotta install fish and do some setup’
environment.systemPackages = with pkgs; [ ... firefox ... ]; # the presence of ‘firefox’ in this list tells NixOS that this package must be installed ‘for the whole system’ (all users can get to it)

When the operating system configuration is realized (happens when the user runs nixos-rebuild switch, the fish module and KDE module end up inserting all the necessary dependencies into environment.systemPackages behind the scenes, so explicitly specifying that the user wants those packages installed is not necessary.

If I wanted to install fish without using it as a login shell, I could either include it in the system configuration (/etc/nixos/configuration.nix or some .nix file sourced by it) in the same way as firefox in the example above.

So the module system and the package system are distinct but build upon one another. Adding stuff to vendor_conf.d would mean changing the initialization behavior at the package level instead of the module level, which is not comparable to the way we initialize any other shells. The same goes for modifying __fish_build_paths. We could just have that look for a file in a special place (perhaps /etc/fish/nix.init.fish) and source it if it exists. Then the NixOS module can drop that file into place if necessary, and otherwise it won't affect other users.

So in that sense it's a configuration "wizard"? And if I understand Nix correctly this all ends up as part of the package, in the exact state the user picked?

NixOS could be described as an operating-system level declarative configuration management tool. The way that Nix realizes package installation and the way it realizes other system configuration tasks are essentially the same, but technically here it's not the fish package that gets modified but what is called the ‘system profile’. Which is good, since rebuilding fish itself for OS configuration changes would be not be. :-)

The impressions you give about our desiderata in your bulleted list are largely correct. Currently, we insert the configuration stuff we want into the fish config simply using string interpolation, which is built into Nix-the-language. We do have a bunch of variables we want to set early on, and we do not need command substitution but we do use some statements besides export statements. The file which we use for this purpose on my system currently looks like this:

 export EDITOR="nano"
export GDK_PIXBUF_MODULE_FILE="/nix/store/1c0dqfigzrmj0bx0xsx2k8ck2snkcvc8-librsvg-2.40.16/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"
export GST_PLUGIN_SYSTEM_PATH_1_0="/nix/store/hpp2qhic5ihbh4dj2kpmll960xfl5jgb-gstreamer-1.10.4//lib/gstreamer-1.0:/nix/store/xgr1imgcihc1cawhijziz05b98fvzdi1-gst-plugins-base-1.10.4//lib/gstreamer-1.0:/nix/store/yi04qjzm2clcbawppx00aaxdxhvnnx2a-gst-plugins-good-1.10.4//lib/gstreamer-1.0:/nix/store/d7hj5635x8hmp4xk1qaa6h0isbvqah06-gst-plugins-ugly-1.10.4//lib/gstreamer-1.0:/nix/store/1masq8nq5hmpcj9hvs60xyx8ixjb5vsi-gst-plugins-bad-1.10.4//lib/gstreamer-1.0:/nix/store/fmh0c302m0ngcxcjz0iv36v2id5lm65z-gst-libav-1.10.4//lib/gstreamer-1.0"
export GTK_IM_MODULE="xim"
export GTK_PATH="$HOME/.nix-profile/lib/gtk-2.0:$HOME/.nix-profile/lib/gtk-3.0:/nix/var/nix/profiles/default/lib/gtk-2.0:/nix/var/nix/profiles/default/lib/gtk-3.0:/run/current-system/sw/lib/gtk-2.0:/run/current-system/sw/lib/gtk-3.0"
export INFINALITY_FT="ultimate3"
export INFOPATH="$HOME/.nix-profile/info:$HOME/.nix-profile/share/info:/nix/var/nix/profiles/default/info:/nix/var/nix/profiles/default/share/info:/run/current-system/sw/info:/run/current-system/sw/share/info"
export KDEDIRS="$HOME/.nix-profile:/nix/var/nix/profiles/default:/run/current-system/sw"
export LANG="en_US.UTF-8"
export LD_LIBRARY_PATH="/run/opengl-driver/lib:/run/opengl-driver-32/lib"
export LIBEXEC_PATH="$HOME/.nix-profile/lib/libexec:/nix/var/nix/profiles/default/lib/libexec:/run/current-system/sw/lib/libexec"
export LOCALE_ARCHIVE="/run/current-system/sw/lib/locale/locale-archive"
export LOCATE_PATH="/var/cache/locatedb"
export MOZ_PLUGIN_PATH="$HOME/.nix-profile/lib/mozilla/plugins:/nix/var/nix/profiles/default/lib/mozilla/plugins:/run/current-system/sw/lib/mozilla/plugins"
export NIXPKGS_CONFIG="/etc/nix/nixpkgs-config.nix"
export NIX_CONF_DIR="/etc/nix"
export NIX_OTHER_STORES="/run/nix/remote-stores/*/nix"
export NIX_PATH="/etc/nixos:nixos-config=/etc/nixos/configuration.nix"
export PAGER="less -R"
export PATH="$HOME/.nix-profile/bin:$HOME/.nix-profile/sbin:$HOME/.nix-profile/lib/kde4/libexec:/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:/nix/var/nix/profiles/default/lib/kde4/libexec:/run/current-system/sw/bin:/run/current-system/sw/sbin:/run/current-system/sw/lib/kde4/libexec"
export PERL5LIB="$HOME/.nix-profile/lib/perl5/site_perl:/nix/var/nix/profiles/default/lib/perl5/site_perl:/run/current-system/sw/lib/perl5/site_perl"
export PKG_CONFIG_PATH="$HOME/.nix-profile/lib/pkgconfig:/nix/var/nix/profiles/default/lib/pkgconfig:/run/current-system/sw/lib/pkgconfig"
export QT4_IM_MODULE="xim"
export QTWEBKIT_PLUGIN_PATH="$HOME/.nix-profile/lib/mozilla/plugins/:/nix/var/nix/profiles/default/lib/mozilla/plugins/:/run/current-system/sw/lib/mozilla/plugins/"
export QT_IM_MODULE="compose"
export QT_PLUGIN_PATH="$HOME/.nix-profile/lib/qt4/plugins:$HOME/.nix-profile/lib/kde4/plugins:/nix/var/nix/profiles/default/lib/qt4/plugins:/nix/var/nix/profiles/default/lib/kde4/plugins:/run/current-system/sw/lib/qt4/plugins:/run/current-system/sw/lib/kde4/plugins"
export SSH_ASKPASS="/nix/store/7if3sm7x91vymf5nyf5q25x2djk9fpxm-ksshaskpass-5.8.6/bin/ksshaskpass"
export STRIGI_PLUGIN_PATH="$HOME/.nix-profile/lib/strigi/:/nix/var/nix/profiles/default/lib/strigi/:/run/current-system/sw/lib/strigi/"
export TERMINFO_DIRS="$HOME/.nix-profile/share/terminfo:/nix/var/nix/profiles/default/share/terminfo:/run/current-system/sw/share/terminfo"
export TZDIR="/etc/zoneinfo"
export XCOMPOSEFILE="/etc/XCompose"
export XDG_CONFIG_DIRS="$HOME/.nix-profile/etc/xdg:/nix/var/nix/profiles/default/etc/xdg:/run/current-system/sw/etc/xdg"
export XDG_DATA_DIRS="/run/opengl-driver/share:/run/opengl-driver-32/share:$HOME/.nix-profile/share:/nix/var/nix/profiles/default/share:/run/current-system/sw/share"

EDITOR=vim

# Set up secure multi-user builds: non-root users build through the
# Nix daemon.
if [ "$USER" != root -o ! -w /nix/var/nix/db ]; then
    export NIX_REMOTE=daemon
fi

# Wrappers override other bin directories.
export PATH="/run/wrappers/bin:$PATH"

if [ -z "$SSH_AUTH_SOCK" -a -n "$XDG_RUNTIME_DIR" ]; then
  export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent"
fi

# reset TERM with new TERMINFO available (if any)
export TERM=$TERM

unset ASPELL_CONF
for i in /run/current-system/sw /nix/var/nix/profiles/default $HOME/.nix-profile ; do
  if [ -d "$i/lib/aspell" ]; then
    export ASPELL_CONF="dict-dir $i/lib/aspell"
  fi
done

export NIX_USER_PROFILE_DIR="/nix/var/nix/profiles/per-user/$USER"
export NIX_PROFILES="/run/current-system/sw /nix/var/nix/profiles/default $HOME/.nix-profile"


# The setuid/setcap wrappers override other bin directories.
export PATH="/run/wrappers/bin:$PATH"

# ~/bin if it exists overrides other bin directories.
export PATH="$HOME/bin:$PATH"

To get fish to understand this file without too much pain, we leverage the foreign-env fish plugin from oh-my-fish, which allows us to run bash scripts and import the variable changes they make back into fish. That solution works well, hackish though it is.

Your explanation of the way fish sourcing currently works was very clear and quite helpful. For the short term, all we need to do is figure out where to hook in; NixOS already takes care of pulling the fenv plugin down, and it knows precisely where it lives, so adding it to the fish_function_path is just a matter of string interpolation in whatever config file we generate for initializing fish. So if we can have a place to drop a fish script, we can make sure that the fish script can successfully call fenv on the sh script NixOS is already using.

I'm thinking the following would be natural, let me know what you think

  • have __fish_build_paths source $__fish_sysconfdir/preinit.fish if it exists
  • put a simple script like test -f /etc/fish/nix-init.fish; and source /etc/fish/nix-init.fish in $__fish_sysconfdir/preinit.fish as part of the Nix package for fish
  • have the NixOS module for fish create a /etc/fish/nix-init.fish file which uses fenv to set all the variables using the POSIX scripts NixOS generates for other login shells (bash, zsh, etc.)

PS: The distinction between $__fish_sysconfdir and /etc/fish on NixOS is important. Because of the way Nix isolates its packages from one another (so it can selectively reunite them in a controlled way), $__fish_sysconfdir ends up being under a package-specific etc. To illustrate

~  ls -lh /etc/fish                                                                           Mon 27 Mar 2017 03:44:46 PM MST
total 4.0K
lrwxrwxrwx 1 root root   28 Mar 27 14:35 config.fish -> /etc/static/fish/config.fish
drwxr-xr-x 2 root root 4.0K Mar 27 14:35 foreign-env
~  realpath /etc/fish/config.fish                                                             Mon 27 Mar 2017 03:44:49 PM MST
/nix/store/vvjg7hwhcbs49zyfzfibrsv4v48xpaq4-etc-config.fish
~  cat $__fish_sysconfdir/config.fish                                                         Mon 27 Mar 2017 03:44:55 PM MST
# Put system-wide fish configuration entries here
# or in .fish files in conf.d/
# Files in conf.d can be overridden by the user
# by files with the same name in $XDG_CONFIG_HOME/fish/conf.d

# This file is run by all fish instances.
# To include configuration only for login shells, use
# if status --is-login
#    ...
# end
# To include configuration only for interactive shells, use
# if status --is-interactive
#   ...
# end

if test -f /etc/fish/config.fish
  source /etc/fish/config.fish
end

So currently we generate our real /etc/fish/config.fish, which plays the usual role, at the module level. Then at the package level we tell give the fish package a local etc/fish/config.fish which tells it to look for the global one and source it if it exists. What I tried to describe above is doing something similar for the stuff that needs to be sourced early.

@therealpxc
Copy link
Author

therealpxc commented Mar 27, 2017

While I'm here, I'd like to share a cute story:

My love of fish is actually the reason I discovered and started using Nix. A couple years ago, I wanted to use fish on computers in the lab at my university. However, it wasn't installed, and when I asked the administrators about adding it, they told me they only installed software on those systems for faculty who needed them for official projects or classes.

I wasn't satisfied with that answer, so I searched the web for tools I could use to install Linux packages in usermode. Since at the time LinuxBrew didn't have any binary caching, Nix turned out to be the most convenient option. With a little bit of messing around, I was able to install any package in the whole NixOS/Nixpkgs collection with a guarantee that it would not interfere with any system packages. I was delighted. Fish was of course the very first thing I installed with Nix!

I only decided to try NixOS some time later. I'd never have gotten a taste of it if I hadn't been so hungry for fish. :-)

@faho
Copy link
Member

faho commented Mar 27, 2017

To get fish to understand this file without too much pain, we leverage the foreign-env fish plugin from oh-my-fish, which allows us to run bash scripts and import the variable changes they make back into fish. That solution works well, hackish though it is.

Obviously, I don't love this solution. I can see why you need it though.

The example you provided looks like it's composed of parts that fish can deal with (the export stuff, via our compatibility function) and static parts that can be rewritten for it (the ifs and loops and such), but that's probably not guaranteed. (Also, for some reason, you export EDITOR=nano and then set EDITOR=vim - any reason for that?)

PS: The distinction between $__fish_sysconfdir and /etc/fish on NixOS is important.

Oh yes, of course. It's just that I'm used to typing "/etc" to make it easier to digest for new users.

I'm thinking the following would be natural, let me know what you think

That would probably work, I'm just not sure what the indirection is good for. Why not have __fish_build_paths.fish source nix-init.fish if it exists directly?

I only decided to try NixOS some time later. I'd never have gotten a taste of it if I hadn't been so hungry for fish. :-)

Hehe 😄.

@therealpxc
Copy link
Author

therealpxc commented Mar 27, 2017

That would probably work, I'm just not sure what the indirection is good for. Why not have __fish_build_paths.fish source nix-init.fish if it exists directly?

It would be more general, which means that other distros or users who might need similar hooks could more easily take advantage of them. One comes to mind immediately: NixOS has something of a sister project in GuixSD, a GNU distribution whose mechanisms of package and configuration management are inspired by Nix (currently they still share some code deep down, but that may be rewritten at some point), but which uses GNU Guile instead of the Nix language. (Guix has wonderful documentation and a killer Emacs mode, if you're into those things and you'd like to explore these package management concepts some time.)

The example you provided looks like it's composed of parts that fish can deal with (the export stuff, via our compatibility function) and static parts that can be rewritten for it (the ifs and loops and such), but that's probably not guaranteed. (Also, for some reason, you export EDITOR=nano and then set EDITOR=vim - any reason for that?)

Good eye. I'm not sure why it does that. Perhaps just to make sure that $EDITOR has some value and because more sophisticated code generation would be more work. I don't know how that file gets generated, but that would be worth looking into because it's probably around there where we could just emit shell-dependent code instead of always doing POSIX and then wrapping it with fenv for fish. That would also make it easier to add login support for other non-POSIX shells, like Oil Shell or Elvish.

@faho
Copy link
Member

faho commented Mar 28, 2017

It would be more general, which means that other distros or users who might need similar hooks could more easily take advantage of them.

Well, you'd be adding your stuff regardless. I'm proposing you append it to __fish_build_paths.fish or replace that file completely. If you can do that (and the code to do it is borderline trivial), then the additional file doesn't add much value.

Guix has wonderful documentation and a killer Emacs mode

I'm a sucker for a good Emacs mode, yes.

I don't know how that file gets generated, but that would be worth looking into because it's probably around there where we could just emit shell-dependent code instead of always doing POSIX and then wrapping it with fenv for fish.

If it were me, I'd emit "KEY=VALUE" or at least always "export KEY=VALUE", no quotes, value goes to the end of the line. That format is easy to parse for anything. Essentially, dump the output of env and maybe prepend "export".

other non-POSIX shells, like Oil Shell or Elvish.

IIRC, Oil does the hybrid thing of a bash-mode (that is supposed to be compatible except for one corner-case) and a "native" mode. The author has written a lot of interesting stuff about parsing shell scripts.

@therealpxc
Copy link
Author

I did end up solving the NixOS Fish initialization problems in the way you described, @faho . Thanks for helping me to reason through and understand the Fish initialization process!

I will likely reach out again about possibly upstreaming other changes (minor changes to that $__fish_datadir/config.fish file) after I add some more features to Fish's Nix package, but by the time that happens I'll have some cool demos you can play with to show why those changes are worthwhile and sane.

And special thanks again for helping to review my changes on the NixOS PR even though you're not a Nix user. That was very sweet of you. I appreciate it.

Thanks as well to @krader1961 for helping me contextualize this issue in relation to other decisions about the Fish initialization process. Y'all are great, and Fish is a great shell.

@faho faho removed this from the fish-future milestone Jul 24, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants