Step towards supporting multiple shells

Please note that I'd like to push this for discussion - it doesn't mean you have to merge it right now.


bash setup changes:

- new option environment.bashFeatures modularizing bash setup
  implementations based on previous code: prompt, completion, aliases, other
  -> See examples below

- provide /etc/bash/setup-all shell scripts setting those features up
  You can opt out by defining keys in DID_NIX_BASH_FEATURES, use declare -A
  first (see comment)

- provide /etc/skel/.bashrc which by default sources setup-all
  This way users can opt-out. Mind that I wrote a [shadow patch] so that user-add
  creates ~/.bashrc as file, not as symlink

  [shadow patch]: https://github.com/NixOS/nixpkgs/pull/459

- support XML_CATALOG_FILES, so that you can use xmllint like tools without
  having them download dts easily

- introduce nix-bash-lib which provides some helper functions.
  It is sourced as needed.

- export __ETC_PROFILE_DONE, so that profile isn't setup twice

zsh:
  implement the very same.
  Please note that the zshrc hack found in nixpkgs is obsolete then.

Thus a typical .bashrc/ .zshrc of a user looks like this after this patch:

    # opt-out from the completion feature:

    declare -A DID_NIX_BASH_FEATURES
    DID_NIX_BASH_FEATURES["completion"]=1

    # but load everything else the system administrator thinks is useful on
    # this machine:
    source /etc/bash/setup-all

    # custom setup of the user
    ....

Example features zsh:
Note that interactive_code is only loaded for interactive shells whereas
env_code is loaded always

    zsh.availableFeatures = {
      # simple xpath like navigation for the filesystem. Eg open /etc/nixos/configuration.nix by
      # E /enc
      pathSelector.interactive_code = let ps = "${pkgs.misc.pathSelector}/bin/path-selector"; in ''
        autoload -Uz _path_selector
        bindkey '^g' _path_selector
        zle -N _path_selector
        fpath=(${pkgs.misc.pathSelector}/fpath $fpath)

        C()   { cd       $(${ps} "$@"); }
        E()   { $EDITOR  $(${ps} "$@"); }
        MDC() { mdc      $(${ps} "$@"); }
        alias F=${ps}'';

      # setup vi keybindings for zsh, but keep useful mappings like ctrl-a ctrl-e (move to start/end of line)
      vi_setup.interactive_code = ''
        # vi keys
        bindkey -v
        bindkey "^a" beginning-of-line
        bindkey "^e" end-of-line
        bindkey "^p" up-line-or-history
        bindkey "^r" history-incremental-search-backward
      '';

      # provide a function which can be used to install Vim plugin vim-addon-manager
      vam.env_code = ''
        vim-install-vam(){
        mkdir -p ~/.vim/vim-addons \
        && git clone --depth=1 git://github.com/MarcWeber/vim-addon-manager.git ~/.vim/vim-addons/vim-addon-manager \
        && cat >> ~/.vimrc << EOF
        set nocompatible
        filetype indent plugin on | syn on
        fun ActivateAddons()
          let g:vim_addon_manager = {}
          let g:vim_addon_manager.log_to_buf =1
          set runtimepath+=~/.vim/vim-addons/vim-addon-manager
          call vam#ActivateAddons([])
        endf
        call ActivateAddons()
        " experimental: run after gui has been started [3]
        " option1:  au VimEnter * call Activate()
        " option2:  au GUIEnter * call Activate()
        EOF
        }
        '';
    };

TODO: provide other implementations (fish etc)

Signed-off-by: Marc Weber <marco-oweber@gmx.de>