| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 |
|
| 22 | |
| 23 | |
| 24 | |
| 25 | |
| 26 | |
| 27 |
|
| 28 | (define-module (gnu home services shells)
|
| 29 | #:use-module (gnu services configuration)
|
| 30 | #:use-module ((gnu services) #:select (%default-bash-aliases))
|
| 31 | #:autoload (gnu system shadow) (%default-bashrc %default-zprofile)
|
| 32 | #:use-module (gnu home services utils)
|
| 33 | #:use-module (gnu home services)
|
| 34 | #:use-module (gnu packages shells)
|
| 35 | #:use-module (gnu packages bash)
|
| 36 | #:use-module (guix gexp)
|
| 37 | #:use-module (guix packages)
|
| 38 | #:use-module (guix records)
|
| 39 | #:use-module (srfi srfi-1)
|
| 40 | #:use-module (srfi srfi-26)
|
| 41 | #:use-module (ice-9 match)
|
| 42 |
|
| 43 | #:export (home-shell-profile-service-type
|
| 44 | home-shell-profile-configuration
|
| 45 |
|
| 46 | home-bash-service-type
|
| 47 | home-bash-configuration
|
| 48 | home-bash-extension
|
| 49 |
|
| 50 | home-zsh-service-type
|
| 51 | home-zsh-configuration
|
| 52 | home-zsh-extension
|
| 53 |
|
| 54 | home-fish-service-type
|
| 55 | home-fish-configuration
|
| 56 | home-fish-extension
|
| 57 |
|
| 58 | home-inputrc-service-type
|
| 59 | home-inputrc-configuration))
|
| 60 |
|
| 61 |
|
| 62 | |
| 63 | |
| 64 | |
| 65 |
|
| 66 | (define path? string?)
|
| 67 | (define (serialize-path field-name val) val)
|
| 68 |
|
| 69 | (define-configuration home-shell-profile-configuration
|
| 70 | (profile
|
| 71 | (text-config '())
|
| 72 | "\
|
| 73 | @code{home-shell-profile} is instantiated automatically by
|
| 74 | @code{home-environment}, DO NOT create this service manually, it can
|
| 75 | only be extended.
|
| 76 |
|
| 77 | @code{profile} is a list of file-like objects, which will go to
|
| 78 | @file{~/.profile}. By default @file{~/.profile} contains the
|
| 79 | initialization code, which have to be evaluated by login shell to make
|
| 80 | home-environment's profile available to the user, but other commands
|
| 81 | can be added to the file if it is really necessary.
|
| 82 |
|
| 83 | In most cases shell's configuration files are preferred places for
|
| 84 | user's customizations. Extend home-shell-profile service only if you
|
| 85 | really know what you do."))
|
| 86 |
|
| 87 | (define (add-shell-profile-file config)
|
| 88 | `((".profile"
|
| 89 | ,(mixed-text-file
|
| 90 | "shell-profile"
|
| 91 | "\
|
| 92 | HOME_ENVIRONMENT=$HOME/.guix-home
|
| 93 | . $HOME_ENVIRONMENT/setup-environment
|
| 94 | $HOME_ENVIRONMENT/on-first-login
|
| 95 | unset HOME_ENVIRONMENT\n"
|
| 96 | (serialize-configuration
|
| 97 | config
|
| 98 | (filter-configuration-fields
|
| 99 | home-shell-profile-configuration-fields '(profile)))))))
|
| 100 |
|
| 101 | (define (add-profile-extensions config extensions)
|
| 102 | (home-shell-profile-configuration
|
| 103 | (inherit config)
|
| 104 | (profile
|
| 105 | (append (home-shell-profile-configuration-profile config)
|
| 106 | extensions))))
|
| 107 |
|
| 108 | (define home-shell-profile-service-type
|
| 109 | (service-type (name 'home-shell-profile)
|
| 110 | (extensions
|
| 111 | (list (service-extension
|
| 112 | home-files-service-type
|
| 113 | add-shell-profile-file)))
|
| 114 | (compose concatenate)
|
| 115 | (extend add-profile-extensions)
|
| 116 | (default-value (home-shell-profile-configuration))
|
| 117 | (description "Create @file{~/.profile}, which is used
|
| 118 | for environment initialization of POSIX compliant login shells. This
|
| 119 | service type can be extended with a list of file-like objects.")))
|
| 120 |
|
| 121 | (define (serialize-boolean field-name val) "")
|
| 122 | (define (serialize-posix-env-vars field-name val)
|
| 123 | (environment-variable-shell-definitions val))
|
| 124 |
|
| 125 | (define (serialize-shell-variables field value)
|
| 126 | (shell-variable-definitions value))
|
| 127 |
|
| 128 |
|
| 129 | |
| 130 | |
| 131 | |
| 132 |
|
| 133 | (define-configuration home-zsh-configuration
|
| 134 | (package
|
| 135 | (package zsh)
|
| 136 | "The Zsh package to use.")
|
| 137 | (xdg-flavor?
|
| 138 | (boolean #t)
|
| 139 | "Place all the configs to @file{$XDG_CONFIG_HOME/zsh}. Makes
|
| 140 | @file{~/.zshenv} to set @env{ZDOTDIR} to @file{$XDG_CONFIG_HOME/zsh}.
|
| 141 | Shell startup process will continue with
|
| 142 | @file{$XDG_CONFIG_HOME/zsh/.zshenv}.")
|
| 143 | (environment-variables
|
| 144 | (alist '())
|
| 145 | "Association list of environment variables to set for the Zsh session."
|
| 146 | (serializer serialize-posix-env-vars))
|
| 147 | (zshenv
|
| 148 | (text-config '())
|
| 149 | "List of file-like objects, which will be added to @file{.zshenv}.
|
| 150 | Used for setting user's shell environment variables. Must not contain
|
| 151 | commands assuming the presence of tty or producing output. Will be
|
| 152 | read always. Will be read before any other file in @env{ZDOTDIR}.")
|
| 153 | (zprofile
|
| 154 | (text-config '())
|
| 155 | "List of file-like objects, which will be added to @file{.zprofile}.
|
| 156 | Used for executing user's commands at start of login shell (In most
|
| 157 | cases the shell started on tty just after login). Will be read before
|
| 158 | @file{.zlogin}.")
|
| 159 | (zshrc
|
| 160 | (text-config '())
|
| 161 | "List of file-like objects, which will be added to @file{.zshrc}.
|
| 162 | Used for executing user's commands at start of interactive shell (The
|
| 163 | shell for interactive usage started by typing @code{zsh} or by
|
| 164 | terminal app or any other program).")
|
| 165 | (zlogin
|
| 166 | (text-config '())
|
| 167 | "List of file-like objects, which will be added to @file{.zlogin}.
|
| 168 | Used for executing user's commands at the end of starting process of
|
| 169 | login shell.")
|
| 170 | (zlogout
|
| 171 | (text-config '())
|
| 172 | "List of file-like objects, which will be added to @file{.zlogout}.
|
| 173 | Used for executing user's commands at the exit of login shell. It
|
| 174 | won't be read in some cases (if the shell terminates by exec'ing
|
| 175 | another process for example)."))
|
| 176 |
|
| 177 | (define (zsh-filter-fields field)
|
| 178 | (filter-configuration-fields home-zsh-configuration-fields (list field)))
|
| 179 |
|
| 180 | (define (zsh-serialize-field config field)
|
| 181 | (serialize-configuration config (zsh-filter-fields field)))
|
| 182 |
|
| 183 | (define* (zsh-field-not-empty? config field)
|
| 184 | (let ((file-name (symbol->string field))
|
| 185 | (field-obj (car (zsh-filter-fields field))))
|
| 186 | (not (null? ((configuration-field-getter field-obj) config)))))
|
| 187 |
|
| 188 | (define (zsh-file-zshenv config)
|
| 189 | (mixed-text-file
|
| 190 | "zshenv"
|
| 191 | (zsh-serialize-field config 'zshenv)
|
| 192 | (zsh-serialize-field config 'environment-variables)
|
| 193 | "\
|
| 194 | if [ -n \"$SSH_CLIENT\" ]; then
|
| 195 | if [[ -f $ZDOTDIR/.zprofile ]]; then
|
| 196 | source $ZDOTDIR/.zprofile
|
| 197 | else
|
| 198 | source /etc/profile
|
| 199 | fi
|
| 200 | fi
|
| 201 | "))
|
| 202 |
|
| 203 | (define (zsh-file-zprofile config)
|
| 204 | (mixed-text-file
|
| 205 | "zprofile"
|
| 206 | (plain-file-content %default-zprofile)
|
| 207 | "\
|
| 208 | # It's only necessary if zsh is a login shell, otherwise profiles will
|
| 209 | # be already sourced by bash
|
| 210 | "
|
| 211 | (zsh-serialize-field config 'zprofile)))
|
| 212 |
|
| 213 | (define (zsh-file-by-field config field)
|
| 214 | (match field
|
| 215 | ('zshenv (zsh-file-zshenv config))
|
| 216 | ('zprofile (zsh-file-zprofile config))
|
| 217 | (e (mixed-text-file
|
| 218 | (symbol->string field)
|
| 219 | (zsh-serialize-field config field)))))
|
| 220 |
|
| 221 | (define (zsh-get-configuration-files config)
|
| 222 | `((".zprofile" ,(zsh-file-by-field config 'zprofile)) |
| 223 | (".zshenv" ,(zsh-file-by-field config 'zshenv)) |
| 224 | ,@(if (zsh-field-not-empty? config 'zshrc)
|
| 225 | `((".zshrc" ,(zsh-file-by-field config 'zshrc))) '())
|
| 226 | ,@(if (zsh-field-not-empty? config 'zlogin)
|
| 227 | `((".zlogin" ,(zsh-file-by-field config 'zlogin))) '())
|
| 228 | ,@(if (zsh-field-not-empty? config 'zlogout)
|
| 229 | `((".zlogout" ,(zsh-file-by-field config 'zlogout))) '())))
|
| 230 |
|
| 231 | (define (add-zsh-dot-configuration config)
|
| 232 | (define zshenv-auxiliary-file
|
| 233 | (mixed-text-file
|
| 234 | "zshenv-auxiliary"
|
| 235 | "export ZDOTDIR=${XDG_CONFIG_HOME:-$HOME/.config}/zsh\n"
|
| 236 | "[[ -f $ZDOTDIR/.zshenv ]] && source $ZDOTDIR/.zshenv\n"))
|
| 237 |
|
| 238 | (if (home-zsh-configuration-xdg-flavor? config)
|
| 239 | `((".zshenv" ,zshenv-auxiliary-file))
|
| 240 | (zsh-get-configuration-files config)))
|
| 241 |
|
| 242 | (define (add-zsh-xdg-configuration config)
|
| 243 | (if (home-zsh-configuration-xdg-flavor? config)
|
| 244 | (map
|
| 245 | (lambda (lst)
|
| 246 | (cons (string-append "zsh/" (car lst))
|
| 247 | (cdr lst)))
|
| 248 | (zsh-get-configuration-files config))
|
| 249 | '()))
|
| 250 |
|
| 251 | (define (add-zsh-packages config)
|
| 252 | (list (home-zsh-configuration-package config)))
|
| 253 |
|
| 254 | (define-configuration/no-serialization home-zsh-extension
|
| 255 | (environment-variables
|
| 256 | (alist '())
|
| 257 | "Association list of environment variables to set.")
|
| 258 | (zshrc
|
| 259 | (text-config '())
|
| 260 | "List of file-like objects.")
|
| 261 | (zshenv
|
| 262 | (text-config '())
|
| 263 | "List of file-like objects.")
|
| 264 | (zprofile
|
| 265 | (text-config '())
|
| 266 | "List of file-like objects.")
|
| 267 | (zlogin
|
| 268 | (text-config '())
|
| 269 | "List of file-like objects.")
|
| 270 | (zlogout
|
| 271 | (text-config '())
|
| 272 | "List of file-like objects."))
|
| 273 |
|
| 274 | (define (home-zsh-extensions original-config extension-configs)
|
| 275 | (home-zsh-configuration
|
| 276 | (inherit original-config)
|
| 277 | (environment-variables
|
| 278 | (append (home-zsh-configuration-environment-variables original-config)
|
| 279 | (append-map
|
| 280 | home-zsh-extension-environment-variables extension-configs)))
|
| 281 | (zshrc
|
| 282 | (append (home-zsh-configuration-zshrc original-config)
|
| 283 | (append-map
|
| 284 | home-zsh-extension-zshrc extension-configs)))
|
| 285 | (zshenv
|
| 286 | (append (home-zsh-configuration-zshenv original-config)
|
| 287 | (append-map
|
| 288 | home-zsh-extension-zshenv extension-configs)))
|
| 289 | (zprofile
|
| 290 | (append (home-zsh-configuration-zprofile original-config)
|
| 291 | (append-map
|
| 292 | home-zsh-extension-zprofile extension-configs)))
|
| 293 | (zlogin
|
| 294 | (append (home-zsh-configuration-zlogin original-config)
|
| 295 | (append-map
|
| 296 | home-zsh-extension-zlogin extension-configs)))
|
| 297 | (zlogout
|
| 298 | (append (home-zsh-configuration-zlogout original-config)
|
| 299 | (append-map
|
| 300 | home-zsh-extension-zlogout extension-configs)))))
|
| 301 |
|
| 302 | (define home-zsh-service-type
|
| 303 | (service-type (name 'home-zsh)
|
| 304 | (extensions
|
| 305 | (list (service-extension
|
| 306 | home-files-service-type
|
| 307 | add-zsh-dot-configuration)
|
| 308 | (service-extension
|
| 309 | home-xdg-configuration-files-service-type
|
| 310 | add-zsh-xdg-configuration)
|
| 311 | (service-extension
|
| 312 | home-profile-service-type
|
| 313 | add-zsh-packages)))
|
| 314 | (compose identity)
|
| 315 | (extend home-zsh-extensions)
|
| 316 | (default-value (home-zsh-configuration))
|
| 317 | (description "Install and configure Zsh.")))
|
| 318 |
|
| 319 |
|
| 320 | |
| 321 | |
| 322 | |
| 323 |
|
| 324 | (define (bash-serialize-aliases field-name val)
|
| 325 | (with-shell-quotation-bindings
|
| 326 | #~(string-append
|
| 327 | #$@(map
|
| 328 | (match-lambda
|
| 329 | ((key . #f)
|
| 330 | "")
|
| 331 | ((key . #t)
|
| 332 | #~(string-append "alias " #$key "\n"))
|
| 333 | ((key . (? literal-string? value))
|
| 334 | #~(string-append "alias " #$key "="
|
| 335 | (shell-single-quote
|
| 336 | #$(literal-string-value value))
|
| 337 | "\n"))
|
| 338 | ((key . value)
|
| 339 | #~(string-append "alias " #$key "="
|
| 340 | (shell-double-quote #$value)
|
| 341 | "\n")))
|
| 342 | val))))
|
| 343 |
|
| 344 | (define-configuration home-bash-configuration
|
| 345 | (package
|
| 346 | (package bash)
|
| 347 | "The Bash package to use.")
|
| 348 | (guix-defaults?
|
| 349 | |
| 350 | (boolean #t)
|
| 351 | "Add sane defaults like setting @env{PS1}, @env{SHELL}, and ensuring
|
| 352 | @file{/etc/profile} is sourced for non-interactive SSH shells. If you use
|
| 353 | Guix System, is it safe to set this to @code{#f}, as in this case this is
|
| 354 | already taken care of by the globally installed @file{/etc/bashrc}.")
|
| 355 | (environment-variables
|
| 356 | (alist '())
|
| 357 | "Association list of environment variables to set for the Bash session. The
|
| 358 | rules for the @code{home-environment-variables-service-type} apply
|
| 359 | here (@pxref{Essential Home Services}). The contents of this field will be
|
| 360 | added after the contents of the @code{bash-profile} field."
|
| 361 | (serializer serialize-posix-env-vars))
|
| 362 | (variables
|
| 363 | (alist '())
|
| 364 | "Bash variables (not to be confused with environment variables) to be set
|
| 365 | in @file{.bashrc} for use by interactive shells. A typical example of such
|
| 366 | variables is @code{HISTSIZE} and related history variables (@pxref{Bash
|
| 367 | Variables,,, bash, Bash Reference Manual})."
|
| 368 | (serializer serialize-shell-variables))
|
| 369 | (aliases
|
| 370 | (alist %default-bash-aliases)
|
| 371 | "Association list of aliases to set for the Bash session. The aliases will be
|
| 372 | defined after the contents of the @code{bashrc} field has been put in the
|
| 373 | @file{.bashrc} file. The alias will automatically be quoted, so something line
|
| 374 | this:
|
| 375 |
|
| 376 | @lisp
|
| 377 | '((\"ls\" . \"ls -alF\"))
|
| 378 | @end lisp
|
| 379 |
|
| 380 | turns into
|
| 381 |
|
| 382 | @example
|
| 383 | alias ls=\"ls -alF\"
|
| 384 | @end example"
|
| 385 | (serializer bash-serialize-aliases))
|
| 386 | (bash-profile
|
| 387 | (text-config '())
|
| 388 | "List of file-like objects, which will be added to @file{.bash_profile}.
|
| 389 | Used for executing user's commands at start of login shell (In most
|
| 390 | cases the shell started on tty just after login). @file{.bash_login}
|
| 391 | won't be ever read, because @file{.bash_profile} always present.")
|
| 392 | (bashrc
|
| 393 | (text-config '())
|
| 394 | "List of file-like objects, which will be added to @file{.bashrc}.
|
| 395 | Used for executing user's commands at start of interactive shell (The
|
| 396 | shell for interactive usage started by typing @code{bash} or by
|
| 397 | terminal app or any other program).")
|
| 398 | (bash-logout
|
| 399 | (text-config '())
|
| 400 | "List of file-like objects, which will be added to @file{.bash_logout}.
|
| 401 | Used for executing user's commands at the exit of login shell. It
|
| 402 | won't be read in some cases (if the shell terminates by exec'ing
|
| 403 | another process for example)."))
|
| 404 |
|
| 405 | (define (add-bash-configuration config)
|
| 406 | (define (filter-fields field)
|
| 407 | (filter-configuration-fields home-bash-configuration-fields
|
| 408 | (list field)))
|
| 409 |
|
| 410 | (define (serialize-field field)
|
| 411 | (serialize-configuration
|
| 412 | config
|
| 413 | (filter-fields field)))
|
| 414 |
|
| 415 | (define* (file-if-not-empty field #:optional (extra-content #f))
|
| 416 | (let ((file-name (symbol->string field))
|
| 417 | (field-obj (car (filter-fields field))))
|
| 418 | (if (or extra-content
|
| 419 | (not (null? ((configuration-field-getter field-obj) config))))
|
| 420 | `(,(string-append "." (object->snake-case-string file-name))
|
| 421 | ,(apply mixed-text-file
|
| 422 | (object->snake-case-string file-name)
|
| 423 | (append (or extra-content '())
|
| 424 | (list (serialize-field field)))))
|
| 425 | '())))
|
| 426 |
|
| 427 | (filter
|
| 428 | (negate null?)
|
| 429 | `((".bash_profile"
|
| 430 | ,(mixed-text-file
|
| 431 | "bash_profile"
|
| 432 | "\
|
| 433 | # Set up the system, user profile, and related variables.
|
| 434 | # /etc/profile will be sourced by bash automatically
|
| 435 | # Set up the home environment profile.
|
| 436 | if [ -f ~/.profile ]; then source ~/.profile; fi
|
| 437 |
|
| 438 | # Honor per-interactive-shell startup file
|
| 439 | if [ -f ~/.bashrc ]; then
|
| 440 | # Taking care not to source it in the case of a non-interactive SSH
|
| 441 | # shell, to avoid recursion.
|
| 442 | [[ $- != *i* && -n $SSH_CLIENT ]] || . ~/.bashrc
|
| 443 | fi
|
| 444 | "
|
| 445 |
|
| 446 | (serialize-field 'bash-profile)
|
| 447 | (serialize-field 'environment-variables)))
|
| 448 |
|
| 449 | ,@(list (file-if-not-empty
|
| 450 | 'bashrc
|
| 451 | (let ((user-settings (list (serialize-field 'variables) "\n"
|
| 452 | (serialize-field 'aliases))))
|
| 453 | (if (home-bash-configuration-guix-defaults? config)
|
| 454 | (cons* (plain-file-content %default-bashrc) "\n"
|
| 455 | user-settings)
|
| 456 | user-settings)))
|
| 457 | (file-if-not-empty 'bash-logout)))))
|
| 458 |
|
| 459 | (define (add-bash-packages config)
|
| 460 | (list (home-bash-configuration-package config)))
|
| 461 |
|
| 462 | (define-configuration/no-serialization home-bash-extension
|
| 463 | (environment-variables
|
| 464 | (alist '())
|
| 465 | "Additional environment variables to set. These will be combined with the
|
| 466 | environment variables from other extensions and the base service to form one
|
| 467 | coherent block of environment variables.")
|
| 468 | (variables
|
| 469 | (alist '())
|
| 470 | "Extra Bash variables (not to be confused with environment variables) to be
|
| 471 | set in @file{.bashrc} for use by interactive shells.")
|
| 472 | (aliases
|
| 473 | (alist '())
|
| 474 | "Additional aliases to set. These will be combined with the aliases from
|
| 475 | other extensions and the base service.")
|
| 476 | (bash-profile
|
| 477 | (text-config '())
|
| 478 | "Additional text blocks to add to @file{.bash_profile}, which will be combined
|
| 479 | with text blocks from other extensions and the base service.")
|
| 480 | (bashrc
|
| 481 | (text-config '())
|
| 482 | "Additional text blocks to add to @file{.bashrc}, which will be combined
|
| 483 | with text blocks from other extensions and the base service.")
|
| 484 | (bash-logout
|
| 485 | (text-config '())
|
| 486 | "Additional text blocks to add to @file{.bash_logout}, which will be combined
|
| 487 | with text blocks from other extensions and the base service."))
|
| 488 |
|
| 489 | (define (home-bash-extensions original-config extension-configs)
|
| 490 | (match-record original-config <home-bash-configuration>
|
| 491 | (environment-variables variables aliases bash-profile bashrc bash-logout)
|
| 492 | (home-bash-configuration
|
| 493 | (inherit original-config)
|
| 494 | (environment-variables
|
| 495 | (append environment-variables
|
| 496 | (append-map
|
| 497 | home-bash-extension-environment-variables extension-configs)))
|
| 498 | (variables
|
| 499 | (append variables
|
| 500 | (append-map
|
| 501 | home-bash-extension-variables extension-configs)))
|
| 502 | (aliases
|
| 503 | (append aliases
|
| 504 | (append-map
|
| 505 | home-bash-extension-aliases extension-configs)))
|
| 506 | (bash-profile
|
| 507 | (append bash-profile
|
| 508 | (append-map
|
| 509 | home-bash-extension-bash-profile extension-configs)))
|
| 510 | (bashrc
|
| 511 | (append bashrc
|
| 512 | (append-map
|
| 513 | home-bash-extension-bashrc extension-configs)))
|
| 514 | (bash-logout
|
| 515 | (append bash-logout
|
| 516 | (append-map
|
| 517 | home-bash-extension-bash-logout extension-configs))))))
|
| 518 |
|
| 519 | (define home-bash-service-type
|
| 520 | (service-type (name 'home-bash)
|
| 521 | (extensions
|
| 522 | (list (service-extension
|
| 523 | home-files-service-type
|
| 524 | add-bash-configuration)
|
| 525 | (service-extension
|
| 526 | home-profile-service-type
|
| 527 | add-bash-packages)))
|
| 528 | (compose identity)
|
| 529 | (extend home-bash-extensions)
|
| 530 | (default-value (home-bash-configuration))
|
| 531 | (description "Install and configure GNU Bash.")))
|
| 532 |
|
| 533 |
|
| 534 | |
| 535 | |
| 536 | |
| 537 |
|
| 538 | (define (serialize-fish-aliases field-name val)
|
| 539 | #~(string-append
|
| 540 | #$@(map (match-lambda
|
| 541 | ((key . value)
|
| 542 | #~(string-append "alias " #$key " \"" #$value "\"\n"))
|
| 543 | (_ ""))
|
| 544 | val)))
|
| 545 |
|
| 546 | (define (serialize-fish-abbreviations field-name val)
|
| 547 | #~(string-append
|
| 548 | #$@(map (match-lambda
|
| 549 | ((key . value)
|
| 550 | #~(string-append "abbr --add " #$key " " #$value "\n"))
|
| 551 | (_ ""))
|
| 552 | val)))
|
| 553 |
|
| 554 | (define (serialize-fish-env-vars field-name val)
|
| 555 | #~(string-append
|
| 556 | #$@(map (match-lambda
|
| 557 | ((key . #f)
|
| 558 | "")
|
| 559 | ((key . #t)
|
| 560 | #~(string-append "set -x " #$key "\n"))
|
| 561 | ((key . value)
|
| 562 | #~(string-append "set -x " #$key " " #$value "\n")))
|
| 563 | val)))
|
| 564 |
|
| 565 | (define-configuration home-fish-configuration
|
| 566 | (package
|
| 567 | (package fish)
|
| 568 | "The Fish package to use.")
|
| 569 | (config
|
| 570 | (text-config '())
|
| 571 | "List of file-like objects, which will be added to
|
| 572 | @file{$XDG_CONFIG_HOME/fish/config.fish}.")
|
| 573 | (environment-variables
|
| 574 | (alist '())
|
| 575 | "Association list of environment variables to set in Fish."
|
| 576 | (serializer serialize-fish-env-vars))
|
| 577 | (aliases
|
| 578 | (alist '())
|
| 579 | "Association list of aliases for Fish, both the key and the value
|
| 580 | should be a string. An alias is just a simple function that wraps a
|
| 581 | command, If you want something more akin to @dfn{aliases} in POSIX
|
| 582 | shells, see the @code{abbreviations} field."
|
| 583 | (serializer serialize-fish-aliases))
|
| 584 | (abbreviations
|
| 585 | (alist '())
|
| 586 | "Association list of abbreviations for Fish. These are words that,
|
| 587 | when typed in the shell, will automatically expand to the full text."
|
| 588 | (serializer serialize-fish-abbreviations)))
|
| 589 |
|
| 590 | (define (fish-files-service config)
|
| 591 | `(("fish/config.fish"
|
| 592 | ,(mixed-text-file
|
| 593 | "fish-config.fish"
|
| 594 | #~(string-append "\
|
| 595 | # if we haven't sourced the login config, do it
|
| 596 | status --is-login; and not set -q __fish_login_config_sourced
|
| 597 | and begin
|
| 598 |
|
| 599 | set --prepend fish_function_path "
|
| 600 | #$fish-foreign-env
|
| 601 | "/share/fish/functions
|
| 602 | fenv source $HOME/.profile
|
| 603 | set -e fish_function_path[1]
|
| 604 |
|
| 605 | set -g __fish_login_config_sourced 1
|
| 606 |
|
| 607 | end\n\n")
|
| 608 | (serialize-configuration
|
| 609 | config
|
| 610 | home-fish-configuration-fields)))))
|
| 611 |
|
| 612 | (define (fish-profile-service config)
|
| 613 | (list (home-fish-configuration-package config)))
|
| 614 |
|
| 615 | (define-configuration/no-serialization home-fish-extension
|
| 616 | (config
|
| 617 | (text-config '())
|
| 618 | "List of file-like objects for extending the Fish initialization file.")
|
| 619 | (environment-variables
|
| 620 | (alist '())
|
| 621 | "Association list of environment variables to set.")
|
| 622 | (aliases
|
| 623 | (alist '())
|
| 624 | "Association list of Fish aliases.")
|
| 625 | (abbreviations
|
| 626 | (alist '())
|
| 627 | "Association list of Fish abbreviations."))
|
| 628 |
|
| 629 | (define (home-fish-extensions original-config extension-configs)
|
| 630 | (home-fish-configuration
|
| 631 | (inherit original-config)
|
| 632 | (config
|
| 633 | (append (home-fish-configuration-config original-config)
|
| 634 | (append-map
|
| 635 | home-fish-extension-config extension-configs)))
|
| 636 | (environment-variables
|
| 637 | (append (home-fish-configuration-environment-variables original-config)
|
| 638 | (append-map
|
| 639 | home-fish-extension-environment-variables extension-configs)))
|
| 640 | (aliases
|
| 641 | (append (home-fish-configuration-aliases original-config)
|
| 642 | (append-map
|
| 643 | home-fish-extension-aliases extension-configs)))
|
| 644 | (abbreviations
|
| 645 | (append (home-fish-configuration-abbreviations original-config)
|
| 646 | (append-map
|
| 647 | home-fish-extension-abbreviations extension-configs)))))
|
| 648 |
|
| 649 | |
| 650 | |
| 651 | (define home-fish-service-type
|
| 652 | (service-type (name 'home-fish)
|
| 653 | (extensions
|
| 654 | (list (service-extension
|
| 655 | home-xdg-configuration-files-service-type
|
| 656 | fish-files-service)
|
| 657 | (service-extension
|
| 658 | home-profile-service-type
|
| 659 | fish-profile-service)))
|
| 660 | (compose identity)
|
| 661 | (extend home-fish-extensions)
|
| 662 | (default-value (home-fish-configuration))
|
| 663 | (description "\
|
| 664 | Install and configure Fish, the friendly interactive shell.")))
|
| 665 |
|
| 666 |
|
| 667 | |
| 668 | |
| 669 | |
| 670 |
|
| 671 | (define (serialize-inputrc-key-bindings field-name val)
|
| 672 | #~(string-append
|
| 673 | #$@(map
|
| 674 | (match-lambda
|
| 675 | ((key . value)
|
| 676 | #~(string-append #$key ": " #$value "\n")))
|
| 677 | val)))
|
| 678 |
|
| 679 | (define (serialize-inputrc-variables field-name val)
|
| 680 | #~(string-append
|
| 681 | #$@(map
|
| 682 | (match-lambda
|
| 683 | ((key . #f)
|
| 684 | #~(string-append "set " #$key " off\n"))
|
| 685 | ((key . #t)
|
| 686 | #~(string-append "set " #$key " on\n"))
|
| 687 | ((key . value)
|
| 688 | #~(string-append "set " #$key " " #$value "\n")))
|
| 689 | val)))
|
| 690 |
|
| 691 | (define (serialize-inputrc-conditional-constructs field-name val)
|
| 692 | #~(string-append
|
| 693 | #$@(map
|
| 694 | (match-lambda
|
| 695 | (("$endif" . _)
|
| 696 | "$endif\n")
|
| 697 | (("$include" . value)
|
| 698 | #~(string-append "$include " #$value "\n"))
|
| 699 | |
| 700 | ((key . value)
|
| 701 | #~(string-append #$key "\n"
|
| 702 | #$(serialize-configuration
|
| 703 | value
|
| 704 | home-inputrc-configuration-fields))))
|
| 705 | val)))
|
| 706 |
|
| 707 | (define (serialize-inputrc-extra-content field-name value)
|
| 708 | #~(if (string=? #$value "") "" (string-append #$value "\n")))
|
| 709 |
|
| 710 | (define-configuration home-inputrc-configuration
|
| 711 | (key-bindings
|
| 712 | (alist '())
|
| 713 | "Association list of readline key bindings to be added to the
|
| 714 | @code{~/.inputrc} file. This is where code like this:
|
| 715 |
|
| 716 | @lisp
|
| 717 | '((\"Control-l\" . \"clear-screen\"))
|
| 718 | @end lisp
|
| 719 |
|
| 720 | turns into
|
| 721 |
|
| 722 | @example
|
| 723 | Control-l: clear-screen
|
| 724 | @end example"
|
| 725 | (serializer serialize-inputrc-key-bindings))
|
| 726 | (variables
|
| 727 | (alist '())
|
| 728 | "Association list of readline variables to set. This is where configuration
|
| 729 | options like this:
|
| 730 |
|
| 731 | @lisp
|
| 732 | '((\"bell-style\" . \"visible\")
|
| 733 | (\"colored-completion-prefix\" . #t))
|
| 734 | @end lisp
|
| 735 |
|
| 736 | turns into
|
| 737 |
|
| 738 | @example
|
| 739 | set bell-style visible
|
| 740 | set colored-completion-prefix on
|
| 741 | @end example"
|
| 742 | (serializer serialize-inputrc-variables))
|
| 743 | (conditional-constructs
|
| 744 | (alist '())
|
| 745 | "Association list of conditionals to add to the initialization file. This
|
| 746 | includes @command{$if}, @command{else}, @command{endif} and @command{include}
|
| 747 | and they receive a value of another @command{home-inputrc-configuration}.
|
| 748 |
|
| 749 | @lisp
|
| 750 | (conditional-constructs
|
| 751 | `((\"$if mode=vi\" .
|
| 752 | ,(home-inputrc-configuration
|
| 753 | (variables
|
| 754 | `((\"show-mode-in-prompt\" . #t)))))
|
| 755 | (\"$else\" .
|
| 756 | ,(home-inputrc-configuration
|
| 757 | (key-bindings
|
| 758 | `((\"Control-l\" . \"clear-screen\")))))
|
| 759 | (\"$endif\" . #t)))
|
| 760 | @end lisp
|
| 761 |
|
| 762 | turns into
|
| 763 |
|
| 764 | @example
|
| 765 | $if mode=vi
|
| 766 | set show-mode-in-prompt on
|
| 767 | $else
|
| 768 | Control-l: clear-screen
|
| 769 | $endif
|
| 770 | @end example"
|
| 771 | (serializer serialize-inputrc-conditional-constructs))
|
| 772 | (extra-content
|
| 773 | (string "")
|
| 774 | "Extra content appended as-is to the configuration file. Run @command{man
|
| 775 | readline} for more information about all the configuration options."
|
| 776 | (serializer serialize-inputrc-extra-content)))
|
| 777 |
|
| 778 | (define (home-inputrc-files config)
|
| 779 | (list
|
| 780 | `(".inputrc"
|
| 781 | ,(mixed-text-file "inputrc"
|
| 782 | (serialize-configuration
|
| 783 | config
|
| 784 | home-inputrc-configuration-fields)))))
|
| 785 |
|
| 786 | (define home-inputrc-service-type
|
| 787 | (service-type (name 'inputrc)
|
| 788 | (extensions
|
| 789 | (list (service-extension home-files-service-type
|
| 790 | home-inputrc-files)))
|
| 791 | (default-value (home-inputrc-configuration))
|
| 792 | (description "Configure readline in @code{.inputrc}.")))
|
| 793 |
|
| 794 |
|
| 795 | (define (generate-home-shell-profile-documentation)
|
| 796 | (generate-documentation
|
| 797 | `((home-shell-profile-configuration
|
| 798 | ,home-shell-profile-configuration-fields))
|
| 799 | 'home-shell-profile-configuration))
|
| 800 |
|
| 801 | (define (generate-home-bash-documentation)
|
| 802 | (string-append
|
| 803 | (generate-documentation
|
| 804 | `((home-bash-configuration
|
| 805 | ,home-bash-configuration-fields))
|
| 806 | 'home-bash-configuration)
|
| 807 | "\n\n"
|
| 808 | (generate-documentation
|
| 809 | `((home-bash-extension
|
| 810 | ,home-bash-extension-fields))
|
| 811 | 'home-bash-extension)))
|
| 812 |
|
| 813 | (define (generate-home-zsh-documentation)
|
| 814 | (generate-documentation
|
| 815 | `((home-zsh-configuration
|
| 816 | ,home-zsh-configuration-fields))
|
| 817 | 'home-zsh-configuration))
|
| 818 |
|
| 819 | (define (generate-home-fish-documentation)
|
| 820 | (string-append
|
| 821 | (generate-documentation
|
| 822 | `((home-fish-configuration
|
| 823 | ,home-fish-configuration-fields))
|
| 824 | 'home-fish-configuration)
|
| 825 | "\n\n"
|
| 826 | (generate-documentation
|
| 827 | `((home-fish-extension
|
| 828 | ,home-fish-extension-fields))
|
| 829 | 'home-fish-extension)))
|