akinomyoga / ble.sh

Bash Line Editor―a line editor written in pure Bash with syntax highlighting, auto suggestions, vim modes, etc. for Bash interactive sessions.
BSD 3-Clause "New" or "Revised" License
2.68k stars 85 forks source link

[home-manager] What options should be made configurable in home-manager? #216

Closed aiotter closed 1 year ago

aiotter commented 2 years ago

Background

As https://github.com/NixOS/nixpkgs/pull/181963 is getting ready to merge, I'm preparing an home-manager module to enable nix users to manage ~/.blerc along with other settings like ~/.bashrc.

With this module users will be able to configure ble.sh settings like following (copied from my real configuration).

{ lib, config, pkgs, ... }: {
  imports = [ ./modules/blesh ];

  programs.bash = {
    enable = true;
    initExtra = ''
      # Load my plugins
      source "$DOTPATH"/bash/plugins/*.plugin.sh
    '';
  };

  programs.starship = {
    enable = true;
    enableBashIntegration = true;
    settings = lib.trivial.importTOML ./config/starship.toml;
  };

  programs.blesh = {
    enable = true;
    faces = {
      auto_complete = "fg=240";
    };
    imports = [ "contrib/bash-preexec" ];
  };
}

Currently I made it available for seven kinds of options: options for bleopt, hooks for blehook, faces for ble-face, imports for ble-import, importsWithDelay for ble-import -d, and blercExtra to add additional string at the end of generated ~/.blerc.

I'm planning to add the rest, e.g. keymaps for ble-bind, abbreviations for ble-sabbrev, abbreviationCommands for ble-sabbrev -m, etc. I don't think we need to make the options available in home-manager even when they are very complex ones. For example, I'm considering removing hooks option because it seems too complex when we define functions in home-manager. It can be added to blercExtra option if they want.

Question

Do you have any suggestions for which configurations to make available in home-manager and which should not? I don't think the bigger number of options is the better. Small number of highly used options should be available there, and the others are better to be configured in blercExtra. If you can say majority of the sourced scripts can be load with delay, we can source all the scripts listed on imports option with ble-import -d and get rid of importsWithDelay option.

If you want to see how other programs can be configured in home-manager here: https://nix-community.github.io/home-manager/options.html

SuperSandro2000 commented 2 years ago

I would recommend to not implement every setting in home-manager and just use a freeform type. Also managing static configuration files with home-manager adds an extra layer of abstraction which can be inconvenient.

akinomyoga commented 2 years ago

Do you have any suggestions for which configurations to make available in home-manager and which should not?

I don't have a particular opinion on this. It's partly because I'm not a user of home-manager and the idea is not that clear to me. I have read the upstream README and also referenced some articles introducing home-manager, but it just seems to claim to provide declarative configuration. Many questions about the idea of home-manager come to my mind:

If the primary purpose of adding ble.sh to home-manager is to inject ble.sh in ~/.bashrc forged by home-manager, maybe we can just provide configurations that can be specified to the commandline arguments of source ble.sh, such as --rcfile, --noinputrc, and --keep-rlvar? I think we don't have to generate ~/.blerc by default because it can be a problem when one wants to include source ble.sh in ~/.bashrc managed by home-manager but still wants to edit ~/.blerc by the one's own. Maybe we can optionally generate ~/.blerc when specified by the user, but I don't have an idea.

The bash module seems to provide the configuration for a limited pre-defined set of shell variables, shopts, aliases, and the environment variables. It somehow doesn't provide configurations for the keybindings (bind, bind -x, bind -s), the readline variables (bind 'set var val'), and set -o options.

If you can say majority of the sourced scripts can be load with delay, we can source all the scripts listed on imports option with ble-import -d and get rid of importsWithDelay option.

Some of the files need to be sourced immediately. For example, the workaround contrib/bash-preexec needs to be loaded before starship is initialized so cannot be delayed.

I'm planning to add the rest, e.g. keymaps for ble-bind,

Maybe you have an idea, but ble-bind provides different types of keybindings -f, -c, -x, and -s. I think all of these types are equally useful and important. Is it possible to provide all of these different types in a simple interface?

aiotter commented 2 years ago

I'm wondering what is the declarative configuration

Sorry, I have no good answer for this.

What would be the benefits of managing the configuration in a declarative manner?

Home-manager's configuration file is written in Nix. This adds all the configuration programmable using nix expression, e.g. switching some options on for environment A but keeping it off for B. This is especially useful if the configuration file of the program is static like yaml or ini. I doubt it is because of declarative manner, but it is for sure the benefit of home-manager.

For what purposes, and what kind of people use home-manager?

I don't know much about what part of home-manager is the main reason for people to use it, but I guess home-manager is widely used to install packages into user environment and configure it like configuration.nix. Unlike configuration.nix, home-manager is not for system but for user environment.

As for me, I'm using Nix and its fellow projects like home-manager to substitute Ansible. I used to use it for deploying my personal environment, including packages, fonts, system configurations and dotfiles. The main problem is that I had to learn lots about target platform and how to configure it in Ansible's yaml configuration file. Nix minified to maintain OS-specific configurations. With DevOps you can even deploy to the remote environment like Ansible. To accomplish this, I need to store dotfiles including .bashrc and .blesh in my repo and let them copied by home-manager to the right location.

If the primary purpose of adding ble.sh to home-manager is to inject ble.sh in ~/.bashrc forged by home-manager

Primary purpose of adding ble.sh to home-manager is to inject sourcing ble.sh at the beginning of .bashrc and enabling it at the very end of it. If the user is configuring .bashrc in home-manager, there seems no way other than creating home-manager module to accomplish this. My bad, I should have described this at the beginning of the issue!

So essentially there is no need to add declarative options like programs.blesh.faces or programs.blesh.imports I described above. It's just okay to add only one option programs.blesh.blerc and put all the settings there as a string. I just followed how the other programs in home-manager. They tend to have their main configuration options available in home-manager (so that they can set those options programmatically? idk why).

Maybe we can optionally generate ~/.blerc when specified by the user, but I don't have an idea.

Yes, I'm planning to implement it in this way.

Is it possible to provide all of these different types in a simple interface?

I haven't tried to implement options for ble-bind yet, but if it is difficult to map in nix expressions, I just do nothing and let them configure it by themselves using programs.blesh.bleshrcExtra in string form.

akinomyoga commented 2 years ago

@aiotter Great! Thank you for kindly answering all the questions one by one. I now feel comfortable with my current understanding of Home Manager, though I might miss some essence.

I'm wondering what is the declarative configuration

Sorry, I have no good answer for this.

OK, so I guess no one actually knows what it actually means, or at least very limited number of people are allowed to access the esoteric notion of declarative configuration. I see no one explaining what it actually is in the README and articles.

It makes sense to me that home manager allows us to manage the configuration programmaticaly. The explanation of your use case is indeed interesting and is actually what I would have liked to hear.

To conclude, I think I wouldn't have further opinions. I respect your final decision as a user of Home Manager. Thanks for reaching out to me!

SuperSandro2000 commented 2 years ago

I'm wondering what is the declarative configuration

Broken down it means that you are describing your entire system front to back in a programming language rather than actions to configure it. This then allows you to easily remove parts and packages without leaving bloat behind, reference settings from totally different parts, easily template files and enable entire subsystems with simple changes. NixOS is a bit similar to ansible with a few exceptions. For example if ansible fails horrible midway through you can end up with a totally broken system which is very hard to achieve on NixOS. Also it only changes that parts that are changed and does not need to rerun build steps which are already done.

home-manager is just a very similar approach to only the user configuration instead of your entire OS which allows you to use it on eg. Debian.

For example, does it provide additional features like dependency resolution, manipulation from other languages and programs, static analysis, etc? Is that particularly useful for managing the configuration of ble.sh?

Not classical dependency resolution like apt or rpm do but instead each program has its own dependency tree which allows you to potentially mix multiple major versions of libraries. It does not always work but it is easier to achieve than on other distros. You also don't need to super careful at compile to accidentally mix libraries.

For example you can enable nextcloud just with a few settings like your domain name and then nixos module configures your postgres, phpfpm and the nginx virtual host.

For blesh that is not super useful because the configuration is mostly plain shellscript but you could configure all the correct tool requirements very easily.

For what purposes, and what kind of people use home-manager?

Mostly people that want to leverage the declarative features of home-manager like package management for your user configuration but still want/need a old school distro as base which for example works better with proprietary software.

Maybe is this for those who know the syntax of Nix expression language but don't want to learn a specific configuration language of each application?

If you want to fully configure an application you often still need to know the original config syntax. Thats why home-manager is not the best solution to manage configuration files. A dotfile manager often gets you the same and you can still edit all your files.

In that case, are the users of home-manager supposed to switch to the original configuration language when they want to configure the application in more detail? Or they would struggle to continue to use home-manager?

Yes, there is often a setting to append to the configuration file.

akinomyoga commented 2 years ago

Broken down it means that you are describing your entire system front to back in a programming language rather than actions to configure it. This then allows you to easily remove parts and packages without leaving bloat behind, reference settings from totally different parts, easily template files and enable entire subsystems with simple changes. NixOS is a bit similar to ansible with a few exceptions. For example if ansible fails horrible midway through you can end up with a totally broken system which is very hard to achieve on NixOS. Also it only changes that parts that are changed and does not need to rerun build steps which are already done.

[...]

Not classical dependency resolution like apt or rpm do but instead each program has its own dependency tree which allows you to potentially mix multiple major versions of libraries. It does not always work but it is easier to achieve than on other distros. You also don't need to super careful at compile to accidentally mix libraries.

For example you can enable nextcloud just with a few settings like your domain name and then nixos module configures your postgres, phpfpm and the nginx virtual host.

@SuperSandro2000 Thank you very much for your detailed explanation! From your explanation, I could grab a rough picture of the idea of the declarative configuration. So, Home Manager allows us to manage different configuration sets for a set of applications and libraries depending on one another just like NixOS helps us manage multiple versions of applications with dependencies. This is an interesting idea.

If you want to fully configure an application you often still need to know the original config syntax. Thats why home-manager is not the best solution to manage configuration files. A dotfile manager often gets you the same and you can still edit all your files.

I see. So I guess Home Manager becomes the most powerful when we need to manage the connections between different applications and libraries that should be described in multiple configuration files in a consistent way.

akinomyoga commented 1 year ago

I think this issue can be closed. If you have something to discuss further, please reopen it. Thank you!