From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp2 ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms0.migadu.com with LMTPS id WOF5EICOKGEDaAEAgWs5BA (envelope-from ) for ; Fri, 27 Aug 2021 09:04:32 +0200 Received: from aspmx1.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp2 with LMTPS id oEwWDICOKGGLHQAAB5/wlQ (envelope-from ) for ; Fri, 27 Aug 2021 07:04:32 +0000 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 4F1A72E2CC for ; Fri, 27 Aug 2021 09:04:31 +0200 (CEST) Received: from localhost ([::1]:49148 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mJVug-0004lM-Bb for larch@yhetil.org; Fri, 27 Aug 2021 03:04:30 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50800) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mJVuE-0004FN-1A for guix-patches@gnu.org; Fri, 27 Aug 2021 03:04:02 -0400 Received: from debbugs.gnu.org ([209.51.188.43]:39620) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1mJVuD-0001um-Pi for guix-patches@gnu.org; Fri, 27 Aug 2021 03:04:01 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1mJVuD-00054K-L6 for guix-patches@gnu.org; Fri, 27 Aug 2021 03:04:01 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#50208] [PATCH 3/5] home-services: Add shells. Resent-From: Andrew Tropin Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Fri, 27 Aug 2021 07:04:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 50208 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Oleg Pykhalov Cc: 50208@debbugs.gnu.org Received: via spool by 50208-submit@debbugs.gnu.org id=B50208.163004779919427 (code B ref 50208); Fri, 27 Aug 2021 07:04:01 +0000 Received: (at 50208) by debbugs.gnu.org; 27 Aug 2021 07:03:19 +0000 Received: from localhost ([127.0.0.1]:51166 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mJVtT-00053C-9O for submit@debbugs.gnu.org; Fri, 27 Aug 2021 03:03:18 -0400 Received: from mail-lf1-f47.google.com ([209.85.167.47]:34461) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mJVtQ-00052w-8M for 50208@debbugs.gnu.org; Fri, 27 Aug 2021 03:03:13 -0400 Received: by mail-lf1-f47.google.com with SMTP id z2so12425747lft.1 for <50208@debbugs.gnu.org>; Fri, 27 Aug 2021 00:03:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=trop-in.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:in-reply-to:references:date:message-id :mime-version; bh=kFkAQq51sY6nnz0UzrjbQb5vPCTDMxq0alEm43CDP/g=; b=xHbwATZ6uWJ8PdJNRb8jUO575orsBtFsHV7vV21bVVlFw3k7GHtisO5CHwAl0KIzux RkKY4Zz4xUnHeTUzbP5KfjaA1VwQ0XHZZtmhNsAnpsB2TbM8b4X5/zkWhNj05STJ+YP4 HLRPeUnRUDQFiP2WcfDTkjzoLGZ6jmsjUrv0fofBScBJQPaZVdpmVAaLAgJ/gCLhzCYl CaxQmrLV6RcY/qgliHxhnecuc/XC2bDjNR5LFnVIdA2VugAKrTH1VHX9udnUsLvLQ9nn bRJnAjeegETEyf+9SdXlYGUGWAgfagEM9O9UPL+X9zXdrXg6XKR9nUiYXoYP15BCOUS3 eP8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:in-reply-to:references:date :message-id:mime-version; bh=kFkAQq51sY6nnz0UzrjbQb5vPCTDMxq0alEm43CDP/g=; b=YWXHL2ZZh87fO6mi81gYEfmF68l0exPmzPiHdD/A6riIfUTeEgKbDblqI2P3kQCZKZ jGjCvygn5kOp8NU3g18DWx6wx6gDp4B1Zpu9RJXkCR3TZ4mPAutLtyocZF7IXzgdS7rS xnv1eqMb1tTS03s9/64gO5OYptpgTNdb1qwsK86+kmaJPqUsmXYdUC9iyA1WftQeNiy/ d6XDIMkYazCLCb6MuJGnK5rqoJdFjMQSD7eRe2n6qT8VXpheYESsrk7DdZbMpmaLTIiS 5fTBhSuqrUEJFwTFMAH4S3V0iNkyCvwuhUPN1Yal5FBhxcg1TBoLIjcLwG3v5RbcAMMs XH2Q== X-Gm-Message-State: AOAM531bbdXot3R5u5cn0tyWWomLOcMMXyrmneRsqT2sxjjvJjYmzU5L yySp5ja7k3F5IXOeOe5jhkrVEsfVsixSBw== X-Google-Smtp-Source: ABdhPJxIPBH1SyXvScMJraROLn1Xwp8+lyFzf8fQzmd0UtXjMDCGm9ZXvuyp1GfpNXVmi3nSyir24Q== X-Received: by 2002:a19:4f1a:: with SMTP id d26mr5427643lfb.377.1630047786281; Fri, 27 Aug 2021 00:03:06 -0700 (PDT) Received: from localhost (109-252-93-92.nat.spd-mgts.ru. [109.252.93.92]) by smtp.gmail.com with ESMTPSA id e8sm582872ljj.132.2021.08.27.00.03.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Aug 2021 00:03:05 -0700 (PDT) From: Andrew Tropin In-Reply-To: <871r6ffklu.fsf@trop.in> References: <87bl5kbsk8.fsf@trop.in> <87r1eg8obm.fsf@gmail.com> <871r6ffklu.fsf@trop.in> Date: Fri, 27 Aug 2021 10:03:02 +0300 Message-ID: <87r1efe5eh.fsf@trop.in> MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha512; protocol="application/pgp-signature" X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: "Guix-patches" X-Migadu-Flow: FLOW_IN ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1630047871; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:resent-cc:resent-from:resent-sender: resent-message-id:in-reply-to:in-reply-to:references:references: list-id:list-help:list-unsubscribe:list-subscribe:list-post: dkim-signature; bh=lD4jVQLIw/zd3GHZWMD2iqOkR3Xsc6MZhVzUHanentk=; b=geiLxEPkkol9QnLdDFqYq91/0enT4Zy0j52xn+RJeIAXzAM489bGqwfuB/mZy3Tzk+oqC8 vwebNX4Bmc/UqfysZRXyIqI8mi5bTs+QcfaP9Ypuspn0q/H7Xz0W39mPdEduxr+eHpo7es zJ1VoZoRhm9BYdYXvaq2h8Y3EJQ4wsVecsM993nMDE4Rouw1Is9NHw3OCHJccYIjf7ms+g pYBcickhj8lL9k+EBqUOw9KHIoR4GH80xs6aWSJp1J+LxKytY1yICT3yQkE8CR+cY2FoLM W48jj2/rmkMuqFZ3+mbTqflBDbM3b/OS1ePU9arA2ESC9nN5v+ZQ0BVtNPPbTw== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1630047871; a=rsa-sha256; cv=none; b=tq8S/9Oi9jdK10HwRA6VhsPt1jwBLunmOy8qy6z8cDmPb0zPGq/QcFd02KGIF/0ra9OPik 4zGzu45cUcaRYtUvxjjLfaXVpwq00Rp7a4DPNBFHLpC0dNp/fAhIA9pTCaRK2bdRy4N7uv x3ZZ3a6ZxOf8zWWViQXYp1FJrK/FEIV2N7XV1UWvhKuvAyAqpedhY2NKVjdA1JFiCBol/8 7txllbIDicu8v9O3H0uh29RepcnYkbZgEzNLzJN19ZXYA43gXNQxbWPUhUIRmQjrTviVmx oU71wCR9NbTngmlMQJki1sIWVPds0w4+GKMEh/DMuUUCPWcau742e9VgZ1q9Ww== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=fail ("body hash did not verify") header.d=trop-in.20150623.gappssmtp.com header.s=20150623 header.b=xHbwATZ6; spf=pass (aspmx1.migadu.com: domain of guix-patches-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=guix-patches-bounces@gnu.org X-Migadu-Spam-Score: -3.53 Authentication-Results: aspmx1.migadu.com; dkim=fail ("body hash did not verify") header.d=trop-in.20150623.gappssmtp.com header.s=20150623 header.b=xHbwATZ6; dmarc=none; spf=pass (aspmx1.migadu.com: domain of guix-patches-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=guix-patches-bounces@gnu.org X-Migadu-Queue-Id: 4F1A72E2CC X-Spam-Score: -3.53 X-Migadu-Scanner: scn0.migadu.com X-TUID: ioXTlxICqdDB --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable * gnu/home-services/shells.scm (home-shell-profile-service-type, home-shell-profile-configuration) (home-bash-service-type, home-bash-configuration, home-bash-extension) (home-zsh-service-type, home-zsh-configuration, home-zsh-extension) (home-fish-service-type, home-fish-configuration, home-fish-extension): New variables. * gnu/local.mk (GNU_SYSTEM_MODULES): Add home-services/shells.scm. =2D-- gnu/home-services/shells.scm | 637 +++++++++++++++++++++++++++++++++++ gnu/local.mk | 1 + 2 files changed, 638 insertions(+) create mode 100644 gnu/home-services/shells.scm diff --git a/gnu/home-services/shells.scm b/gnu/home-services/shells.scm new file mode 100644 index 0000000000..0643019361 =2D-- /dev/null +++ b/gnu/home-services/shells.scm @@ -0,0 +1,637 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright =C2=A9 2021 Andrew Tropin +;;; Copyright =C2=A9 2021 Xinglu Chen +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (gnu home-services shells) + #:use-module (gnu services configuration) + #:use-module (gnu home-services configuration) + #:use-module (gnu home-services) + #:use-module (gnu packages shells) + #:use-module (gnu packages bash) + #:use-module (guix gexp) + #:use-module (guix packages) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) + #:use-module (ice-9 match) + + #:export (home-shell-profile-service-type + home-shell-profile-configuration + + home-bash-service-type + home-bash-configuration + home-bash-extension + + home-zsh-service-type + home-zsh-configuration + home-zsh-extension + + home-fish-service-type + home-fish-configuration + home-fish-extension)) + +;;; Commentary: +;;; +;;; This module contains shell related services like Zsh. +;;; +;;; Code: + + +;;; +;;; Shell profile. +;;; + +(define path? string?) +(define (serialize-path field-name val) val) + +(define-configuration home-shell-profile-configuration + (profile + (text-config '()) + "\ +@code{home-shell-profile} is instantiated automatically by +@code{home-environment}, DO NOT create this service manually, it can +only be extended. + +@code{profile} is a list of strings or gexps, which will go to +@file{~/.profile}. By default @file{~/.profile} contains the +initialization code, which have to be evaluated by login shell to make +home-environment's profile avaliable to the user, but other commands +can be added to the file if it is really necessary. + +In most cases shell's configuration files are preferred places for +user's customizations. Extend home-shell-profile service only if you +really know what you do.")) + +(define (add-shell-profile-file config) + `(("profile" + ,(mixed-text-file + "shell-profile" + "\ +HOME_ENVIRONMENT=3D$HOME/.guix-home +. $HOME_ENVIRONMENT/setup-environment +$HOME_ENVIRONMENT/on-first-login\n" + (serialize-configuration + config + (filter-configuration-fields + home-shell-profile-configuration-fields '(profile))))))) + +(define (add-profile-extensions config extensions) + (home-shell-profile-configuration + (inherit config) + (profile + (append (home-shell-profile-configuration-profile config) + extensions)))) + +(define home-shell-profile-service-type + (service-type (name 'home-shell-profile) + (extensions + (list (service-extension + home-files-service-type + add-shell-profile-file))) + (compose concatenate) + (extend add-profile-extensions) + (default-value (home-shell-profile-configuration)) + (description "Create @file{~/.profile}, which is used +for environment initialization of POSIX compliant login shells. This +service type can be extended with a list of strings or gexps."))) + +(define (serialize-boolean field-name val) "") +(define (serialize-posix-env-vars field-name val) + #~(string-append + #$@(map + (match-lambda + ((key . #f) + "") + ((key . #t) + #~(string-append "export " #$key "\n")) + ((key . value) + #~(string-append "export " #$key "=3D" #$value "\n"))) + val))) + + +;;; +;;; Zsh. +;;; + +(define-configuration home-zsh-configuration + (package + (package zsh) + "The Zsh package to use.") + (xdg-flavor? + (boolean #t) + "Place all the configs to @file{$XDG_CONFIG_HOME/zsh}. Makes +@file{~/.zshenv} to set @env{ZDOTDIR} to @file{$XDG_CONFIG_HOME/zsh}. +Shell startup process will continue with +@file{$XDG_CONFIG_HOME/zsh/.zshenv}.") + (environment-variables + (alist '()) + "Association list of environment variables to set for the Zsh session." + serialize-posix-env-vars) + (zshenv + (text-config '()) + "List of strings or gexps, which will be added to @file{.zshenv}. +Used for setting user's shell environment variables. Must not contain +commands assuming the presence of tty or producing output. Will be +read always. Will be read before any other file in @env{ZDOTDIR}.") + (zprofile + (text-config '()) + "List of strings or gexps, which will be added to @file{.zprofile}. +Used for executing user's commands at start of login shell (In most +cases the shell started on tty just after login). Will be read before +@file{.zlogin}.") + (zshrc + (text-config '()) + "List of strings or gexps, which will be added to @file{.zshrc}. +Used for executing user's commands at start of interactive shell (The +shell for interactive usage started by typing @code{zsh} or by +terminal app or any other program).") + (zlogin + (text-config '()) + "List of strings or gexps, which will be added to @file{.zlogin}. +Used for executing user's commands at the end of starting process of +login shell.") + (zlogout + (text-config '()) + "List of strings or gexps, which will be added to @file{.zlogout}. +Used for executing user's commands at the exit of login shell. It +won't be read in some cases (if the shell terminates by exec'ing +another process for example).")) + +(define (add-zsh-configuration config) + (let* ((xdg-flavor? (home-zsh-configuration-xdg-flavor? config))) + + (define prefix-file + (cut string-append + (if xdg-flavor? + "config/zsh/." + "") <>)) + + (define (filter-fields field) + (filter-configuration-fields home-zsh-configuration-fields + (list field))) + + (define (serialize-field field) + (serialize-configuration + config + (filter-fields field))) + + (define (file-if-not-empty field) + (let ((file-name (symbol->string field)) + (field-obj (car (filter-fields field)))) + (if (not (null? ((configuration-field-getter field-obj) config))) + `(,(prefix-file file-name) + ,(mixed-text-file + file-name + (serialize-field field))) + '()))) + + (filter + (compose not null?) + `(,(if xdg-flavor? + `("zshenv" + ,(mixed-text-file + "auxiliary-zshenv" + (if xdg-flavor? + "source ${XDG_CONFIG_HOME:-$HOME/.config}/zsh/.zshenv\= n" + ""))) + '()) + (,(prefix-file "zshenv") + ,(mixed-text-file + "zshenv" + (if xdg-flavor? + "export ZDOTDIR=3D${XDG_CONFIG_HOME:-$HOME/.config}/zsh\n" + "") + (serialize-field 'zshenv) + (serialize-field 'environment-variables))) + (,(prefix-file "zprofile") + ,(mixed-text-file + "zprofile" + "\ +# Setups system and user profiles and related variables +source /etc/profile +# Setups home environment profile +source ~/.profile + +# It's only necessary if zsh is a login shell, otherwise profiles will +# be already sourced by bash +" + (serialize-field 'zprofile))) + + ,@(list (file-if-not-empty 'zshrc) + (file-if-not-empty 'zlogin) + (file-if-not-empty 'zlogout)))))) + +(define (add-zsh-packages config) + (list (home-zsh-configuration-package config))) + +(define-configuration/no-serialization home-zsh-extension + (environment-variables + (alist '()) + "Association list of environment variables to set.") + (zshrc + (text-config '()) + "List of strings or gexps.") + (zshenv + (text-config '()) + "List of strings or gexps.") + (zprofile + (text-config '()) + "List of strings or gexps.") + (zlogin + (text-config '()) + "List of strings or gexps.") + (zlogout + (text-config '()) + "List of strings or gexps.")) + +(define (home-zsh-extensions original-config extension-configs) + (home-zsh-configuration + (inherit original-config) + (environment-variables + (append (home-zsh-configuration-environment-variables original-config) + (append-map + home-zsh-extension-environment-variables extension-configs))) + (zshrc + (append (home-zsh-configuration-zshrc original-config) + (append-map + home-zsh-extension-zshrc extension-configs))) + (zshenv + (append (home-zsh-configuration-zshenv original-config) + (append-map + home-zsh-extension-zshenv extension-configs))) + (zprofile + (append (home-zsh-configuration-zprofile original-config) + (append-map + home-zsh-extension-zprofile extension-configs))) + (zlogin + (append (home-zsh-configuration-zlogin original-config) + (append-map + home-zsh-extension-zlogin extension-configs))) + (zlogout + (append (home-zsh-configuration-zlogout original-config) + (append-map + home-zsh-extension-zlogout extension-configs))))) + +(define home-zsh-service-type + (service-type (name 'home-zsh) + (extensions + (list (service-extension + home-files-service-type + add-zsh-configuration) + (service-extension + home-profile-service-type + add-zsh-packages))) + (compose identity) + (extend home-zsh-extensions) + (default-value (home-zsh-configuration)) + (description "Install and configure Zsh."))) + + +;;; +;;; Bash. +;;; + +(define-configuration home-bash-configuration + (package + (package bash) + "The Bash package to use.") + (guix-defaults? + (boolean #t) + "Add sane defaults like reading @file{/etc/bashrc}, coloring output +for @code{ls} provided by guix to @file{.bashrc}.") + (environment-variables + (alist '()) + "Association list of environment variables to set for the Bash session." + serialize-posix-env-vars) + (bash-profile + (text-config '()) + "List of strings or gexps, which will be added to @file{.bash_profile}. +Used for executing user's commands at start of login shell (In most +cases the shell started on tty just after login). @file{.bash_login} +won't be ever read, because @file{.bash_profile} always present.") + (bashrc + (text-config '()) + "List of strings or gexps, which will be added to @file{.bashrc}. +Used for executing user's commands at start of interactive shell (The +shell for interactive usage started by typing @code{bash} or by +terminal app or any other program).") + (bash-logout + (text-config '()) + "List of strings or gexps, which will be added to @file{.bash_logout}. +Used for executing user's commands at the exit of login shell. It +won't be read in some cases (if the shell terminates by exec'ing +another process for example).")) + +;; TODO: Use value from (gnu system shadow) +(define guix-bashrc + "\ +# Bash initialization for interactive non-login shells and +# for remote shells (info \"(bash) Bash Startup Files\"). + +# Export 'SHELL' to child processes. Programs such as 'screen' +# honor it and otherwise use /bin/sh. +export SHELL + +if [[ $- !=3D *i* ]] +then + # We are being invoked from a non-interactive shell. If this + # is an SSH session (as in \"ssh host command\"), source + # /etc/profile so we get PATH and other essential variables. + [[ -n \"$SSH_CLIENT\" ]] && source /etc/profile + + # Don't do anything else. + return +fi + +# Source the system-wide file. +source /etc/bashrc + +# Adjust the prompt depending on whether we're in 'guix environment'. +if [ -n \"$GUIX_ENVIRONMENT\" ] +then + PS1=3D'\\u@\\h \\w [env]\\$ ' +else + PS1=3D'\\u@\\h \\w\\$ ' +fi +alias ls=3D'ls -p --color=3Dauto' +alias ll=3D'ls -l' +alias grep=3D'grep --color=3Dauto'\n") + +(define (add-bash-configuration config) + (define (filter-fields field) + (filter-configuration-fields home-bash-configuration-fields + (list field))) + + (define (serialize-field field) + (serialize-configuration + config + (filter-fields field))) + + (define* (file-if-not-empty field #:optional (extra-content #f)) + (let ((file-name (symbol->string field)) + (field-obj (car (filter-fields field)))) + (if (or extra-content + (not (null? ((configuration-field-getter field-obj) config))= )) + `(,(object->snake-case-string file-name) + ,(mixed-text-file + (object->snake-case-string file-name) + (if extra-content extra-content "") + (serialize-field field))) + '()))) + + (filter + (compose not null?) + `(("bash_profile" + ,(mixed-text-file + "bash_profile" + "\ +# Setups system and user profiles and related variables +# /etc/profile will be sourced by bash automatically +# Setups home environment profile +if [ -f ~/.profile ]; then source ~/.profile; fi + +# Honor per-interactive-shell startup file +if [ -f ~/.bashrc ]; then source ~/.bashrc; fi +" + (serialize-field 'bash-profile) + (serialize-field 'environment-variables))) + + ,@(list (file-if-not-empty + 'bashrc + (if (home-bash-configuration-guix-defaults? config) + guix-bashrc + #f)) + (file-if-not-empty 'bash-logout))))) + +(define (add-bash-packages config) + (list (home-bash-configuration-package config))) + +(define-configuration/no-serialization home-bash-extension + (environment-variables + (alist '()) + "Association list of environment variables to set.") + (bash-profile + (text-config '()) + "List of strings or gexps.") + (bashrc + (text-config '()) + "List of strings or gexps.") + (bash-logout + (text-config '()) + "List of strings or gexps.")) + +(define (home-bash-extensions original-config extension-configs) + (home-bash-configuration + (inherit original-config) + (environment-variables + (append (home-bash-configuration-environment-variables original-config) + (append-map + home-bash-extension-environment-variables extension-configs))) + (bash-profile + (append (home-bash-configuration-bash-profile original-config) + (append-map + home-bash-extension-bash-profile extension-configs))) + (bashrc + (append (home-bash-configuration-bashrc original-config) + (append-map + home-bash-extension-bashrc extension-configs))) + (bash-logout + (append (home-bash-configuration-bash-logout original-config) + (append-map + home-bash-extension-bash-logout extension-configs))))) + +(define home-bash-service-type + (service-type (name 'home-bash) + (extensions + (list (service-extension + home-files-service-type + add-bash-configuration) + (service-extension + home-profile-service-type + add-bash-packages))) + (compose identity) + (extend home-bash-extensions) + (default-value (home-bash-configuration)) + (description "Install and configure GNU Bash."))) + + +;;; +;;; Fish. +;;; + +(define (serialize-fish-aliases field-name val) + #~(string-append + #$@(map (match-lambda + ((key . value) + #~(string-append "alias " #$key " \"" #$value "\"\n")) + (_ "")) + val))) + +(define (serialize-fish-abbreviations field-name val) + #~(string-append + #$@(map (match-lambda + ((key . value) + #~(string-append "abbr --add " #$key " " #$value "\n")) + (_ "")) + val))) + +(define (serialize-fish-env-vars field-name val) + #~(string-append + #$@(map (match-lambda + ((key . #f) + "") + ((key . #t) + #~(string-append "set " #$key "\n")) + ((key . value) + #~(string-append "set " #$key " " #$value "\n"))) + val))) + +(define-configuration home-fish-configuration + (package + (package fish) + "The Fish package to use.") + (config + (text-config '()) + "List of strings or gexps, which will be added to +@file{$XDG_CONFIG_HOME/fish/config.fish}.") + (environment-variables + (alist '()) + "Association list of environment variables to set in Fish." + serialize-fish-env-vars) + (aliases + (alist '()) + "Association list of aliases for Fish, both the key and the value +should be a string. An alias is just a simple function that wraps a +command, If you want something more akin to @dfn{aliases} in POSIX +shells, see the @code{abbreviations} field." + serialize-fish-aliases) + (abbreviations + (alist '()) + "Association list of abbreviations for Fish. These are words that, +when typed in the shell, will automatically expand to the full text." + serialize-fish-abbreviations)) + +(define (fish-files-service config) + `(("config/fish/config.fish" + ,(mixed-text-file + "fish-config.fish" + #~(string-append "\ +# if we haven't sourced the login config, do it +status --is-login; and not set -q __fish_login_config_sourced +and begin + + set --prepend fish_function_path " + #$fish-foreign-env + "/share/fish/functions + fenv source $HOME/.profile + set -e fish_function_path[1] + + set -g __fish_login_config_sourced 1 + +end\n\n") + (serialize-configuration + config + home-fish-configuration-fields))))) + +(define (fish-profile-service config) + (list (home-fish-configuration-package config))) + +(define-configuration/no-serialization home-fish-extension + (config + (text-config '()) + "List of strings or gexps for extending the Fish initialization file.") + (environment-variables + (alist '()) + "Association list of environment variables to set.") + (aliases + (alist '()) + "Association list of Fish aliases.") + (abbreviations + (alist '()) + "Association list of Fish abbreviations.")) + +(define (home-fish-extensions original-config extension-configs) + (home-fish-configuration + (inherit original-config) + (config + (append (home-fish-configuration-config original-config) + (append-map + home-fish-extension-config extension-configs))) + (environment-variables + (append (home-fish-configuration-environment-variables original-config) + (append-map + home-fish-extension-environment-variables extension-configs))) + (aliases + (append (home-fish-configuration-aliases original-config) + (append-map + home-fish-extension-aliases extension-configs))) + (abbreviations + (append (home-fish-configuration-abbreviations original-config) + (append-map + home-fish-extension-abbreviations extension-configs))))) + +;; TODO: Support for generating completion files +;; TODO: Support for installing plugins +(define home-fish-service-type + (service-type (name 'home-fish) + (extensions + (list (service-extension + home-files-service-type + fish-files-service) + (service-extension + home-profile-service-type + fish-profile-service))) + (compose identity) + (extend home-fish-extensions) + (default-value (home-fish-configuration)) + (description "\ +Install and configure Fish, the friendly interactive shell."))) + + +(define (generate-home-shell-profile-documentation) + (generate-documentation + `((home-shell-profile-configuration + ,home-shell-profile-configuration-fields)) + 'home-shell-profile-configuration)) + +(define (generate-home-bash-documentation) + (generate-documentation + `((home-bash-configuration + ,home-bash-configuration-fields)) + 'home-bash-configuration)) + +(define (generate-home-zsh-documentation) + (generate-documentation + `((home-zsh-configuration + ,home-zsh-configuration-fields)) + 'home-zsh-configuration)) + +(define (generate-home-fish-documentation) + (string-append + (generate-documentation + `((home-fish-configuration + ,home-fish-configuration-fields)) + 'home-fish-configuration) + "\n\n" + (generate-documentation + `((home-fish-extension + ,home-fish-extension-fields)) + 'home-fish-extension))) + +;; (display (generate-home-shell-profile-documentation)) +;; (display (generate-home-bash-documentation)) +;; (display (generate-home-zsh-documentation)) diff --git a/gnu/local.mk b/gnu/local.mk index e24da4716f..dc0e732114 100644 =2D-- a/gnu/local.mk +++ b/gnu/local.mk @@ -76,6 +76,7 @@ GNU_SYSTEM_MODULES =3D \ %D%/home-services/symlink-manager.scm \ %D%/home-services/fontutils.scm \ %D%/home-services/configuration.scm \ + %D%/home-services/shells.scm \ %D%/image.scm \ %D%/packages.scm \ %D%/packages/abduco.scm \ =2D-=20 2.33.0 --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQJDBAEBCgAtFiEEKEGaxlA4dEDH6S/6IgjSCVjB3rAFAmEojiYPHGFuZHJld0B0 cm9wLmluAAoJECII0glYwd6wQg0P/3p4X/z2of3V2xDBLb6/RFUf8Zd/IJMdLsZm GYIYdR161AGe4VNfg3eqi+/gKaRkDOPIlLq07C8hLAWCddi8nvcSjXUgvIqd1lcD zZDI3psu1rxPwbq5GpF67rnZAI+ddr6x33z5ALOWlpOtOVqLLp9nYRTodJD1NjJC RB75LLEdoGYc1HOwsPYMAgPEPKWQ/HH1K7FI6HW269ez9mtLZj5ERjcSmlDK3oDY s30gqr+Kfg291VlgVTMb4ksOf+pzoZjafZih1qTShmOpUPsLriDv6iNYG5AehxN6 TUGBAIVm0m+yyUCEiTVrQnuZz3jDAOpFkQdxdcxPTtahavVObPaRjpmNPXcnzuTg ZwPo5tvZtIuejQ5oyDNqXqDIukQyYEr48IoT939+DGnV/B5x2Y6jr+9TMDJ9sx3b u9KmsjWvav28hepJmZwC5Ejl5wEA0lSrZOO8OwXu8au0GSLW+7r8r+T1drfBgRg1 FHrq3B3O6l5Zn1HVqGtnJXvGsSWERxzbAFH3yUyA9Oke0rFy6QGgRCog6sldqme8 Zm1YMmuGX4jWJ6dG0hIvlM5EGltGgwZ6tg+swLxem8XWuvIw7PLn2Gf7Gv9Y7Xd/ YaSMGCa7EQ3BFWlREIaKka+t3AYxxY7v3DO2mUA9buq4HfO1SWdQAn5ANmbwNSAz N+TbNVNT =vu+M -----END PGP SIGNATURE----- --=-=-=--