shells.scm 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2021 Andrew Tropin <andrew@trop.in>
  3. ;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
  4. ;;;
  5. ;;; This file is part of GNU Guix.
  6. ;;;
  7. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  8. ;;; under the terms of the GNU General Public License as published by
  9. ;;; the Free Software Foundation; either version 3 of the License, or (at
  10. ;;; your option) any later version.
  11. ;;;
  12. ;;; GNU Guix is distributed in the hope that it will be useful, but
  13. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ;;; GNU General Public License for more details.
  16. ;;;
  17. ;;; You should have received a copy of the GNU General Public License
  18. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  19. (define-module (gnu home services shells)
  20. #:use-module (gnu services configuration)
  21. #:autoload (gnu system shadow) (%default-bashrc)
  22. #:use-module (gnu home services utils)
  23. #:use-module (gnu home services)
  24. #:use-module (gnu packages shells)
  25. #:use-module (gnu packages bash)
  26. #:use-module (guix gexp)
  27. #:use-module (guix packages)
  28. #:use-module (guix records)
  29. #:use-module (srfi srfi-1)
  30. #:use-module (srfi srfi-26)
  31. #:use-module (ice-9 match)
  32. #:export (home-shell-profile-service-type
  33. home-shell-profile-configuration
  34. home-bash-service-type
  35. home-bash-configuration
  36. home-bash-extension
  37. home-zsh-service-type
  38. home-zsh-configuration
  39. home-zsh-extension
  40. home-fish-service-type
  41. home-fish-configuration
  42. home-fish-extension))
  43. ;;; Commentary:
  44. ;;;
  45. ;;; This module contains shell related services like Zsh.
  46. ;;;
  47. ;;; Code:
  48. ;;;
  49. ;;; Shell profile.
  50. ;;;
  51. (define path? string?)
  52. (define (serialize-path field-name val) val)
  53. (define-configuration home-shell-profile-configuration
  54. (profile
  55. (text-config '())
  56. "\
  57. @code{home-shell-profile} is instantiated automatically by
  58. @code{home-environment}, DO NOT create this service manually, it can
  59. only be extended.
  60. @code{profile} is a list of file-like objects, which will go to
  61. @file{~/.profile}. By default @file{~/.profile} contains the
  62. initialization code, which have to be evaluated by login shell to make
  63. home-environment's profile available to the user, but other commands
  64. can be added to the file if it is really necessary.
  65. In most cases shell's configuration files are preferred places for
  66. user's customizations. Extend home-shell-profile service only if you
  67. really know what you do."))
  68. (define (add-shell-profile-file config)
  69. `((".profile"
  70. ,(mixed-text-file
  71. "shell-profile"
  72. "\
  73. HOME_ENVIRONMENT=$HOME/.guix-home
  74. . $HOME_ENVIRONMENT/setup-environment
  75. $HOME_ENVIRONMENT/on-first-login\n"
  76. (serialize-configuration
  77. config
  78. (filter-configuration-fields
  79. home-shell-profile-configuration-fields '(profile)))))))
  80. (define (add-profile-extensions config extensions)
  81. (home-shell-profile-configuration
  82. (inherit config)
  83. (profile
  84. (append (home-shell-profile-configuration-profile config)
  85. extensions))))
  86. (define home-shell-profile-service-type
  87. (service-type (name 'home-shell-profile)
  88. (extensions
  89. (list (service-extension
  90. home-files-service-type
  91. add-shell-profile-file)))
  92. (compose concatenate)
  93. (extend add-profile-extensions)
  94. (default-value (home-shell-profile-configuration))
  95. (description "Create @file{~/.profile}, which is used
  96. for environment initialization of POSIX compliant login shells. This
  97. service type can be extended with a list of file-like objects.")))
  98. (define (serialize-boolean field-name val) "")
  99. (define (serialize-posix-env-vars field-name val)
  100. (environment-variable-shell-definitions val))
  101. ;;;
  102. ;;; Zsh.
  103. ;;;
  104. (define-configuration home-zsh-configuration
  105. (package
  106. (package zsh)
  107. "The Zsh package to use.")
  108. (xdg-flavor?
  109. (boolean #t)
  110. "Place all the configs to @file{$XDG_CONFIG_HOME/zsh}. Makes
  111. @file{~/.zshenv} to set @env{ZDOTDIR} to @file{$XDG_CONFIG_HOME/zsh}.
  112. Shell startup process will continue with
  113. @file{$XDG_CONFIG_HOME/zsh/.zshenv}.")
  114. (environment-variables
  115. (alist '())
  116. "Association list of environment variables to set for the Zsh session."
  117. (serializer serialize-posix-env-vars))
  118. (zshenv
  119. (text-config '())
  120. "List of file-like objects, which will be added to @file{.zshenv}.
  121. Used for setting user's shell environment variables. Must not contain
  122. commands assuming the presence of tty or producing output. Will be
  123. read always. Will be read before any other file in @env{ZDOTDIR}.")
  124. (zprofile
  125. (text-config '())
  126. "List of file-like objects, which will be added to @file{.zprofile}.
  127. Used for executing user's commands at start of login shell (In most
  128. cases the shell started on tty just after login). Will be read before
  129. @file{.zlogin}.")
  130. (zshrc
  131. (text-config '())
  132. "List of file-like objects, which will be added to @file{.zshrc}.
  133. Used for executing user's commands at start of interactive shell (The
  134. shell for interactive usage started by typing @code{zsh} or by
  135. terminal app or any other program).")
  136. (zlogin
  137. (text-config '())
  138. "List of file-like objects, which will be added to @file{.zlogin}.
  139. Used for executing user's commands at the end of starting process of
  140. login shell.")
  141. (zlogout
  142. (text-config '())
  143. "List of file-like objects, which will be added to @file{.zlogout}.
  144. Used for executing user's commands at the exit of login shell. It
  145. won't be read in some cases (if the shell terminates by exec'ing
  146. another process for example)."))
  147. (define (zsh-filter-fields field)
  148. (filter-configuration-fields home-zsh-configuration-fields (list field)))
  149. (define (zsh-serialize-field config field)
  150. (serialize-configuration config (zsh-filter-fields field)))
  151. (define* (zsh-field-not-empty? config field)
  152. (let ((file-name (symbol->string field))
  153. (field-obj (car (zsh-filter-fields field))))
  154. (not (null? ((configuration-field-getter field-obj) config)))))
  155. (define (zsh-file-zshenv config)
  156. (mixed-text-file
  157. "zshenv"
  158. (zsh-serialize-field config 'zshenv)
  159. (zsh-serialize-field config 'environment-variables)))
  160. (define (zsh-file-zprofile config)
  161. (mixed-text-file
  162. "zprofile"
  163. "\
  164. # Set up the system, user profile, and related variables.
  165. source /etc/profile
  166. # Set up the home environment profile.
  167. source ~/.profile
  168. # It's only necessary if zsh is a login shell, otherwise profiles will
  169. # be already sourced by bash
  170. "
  171. (zsh-serialize-field config 'zprofile)))
  172. (define (zsh-file-by-field config field)
  173. (match field
  174. ('zshenv (zsh-file-zshenv config))
  175. ('zprofile (zsh-file-zprofile config))
  176. (e (mixed-text-file
  177. (symbol->string field)
  178. (zsh-serialize-field config field)))))
  179. (define (zsh-get-configuration-files config)
  180. `((".zprofile" ,(zsh-file-by-field config 'zprofile)) ;; Always non-empty
  181. ,@(if (or (zsh-field-not-empty? config 'zshenv)
  182. (zsh-field-not-empty? config 'environment-variables))
  183. `((".zshenv" ,(zsh-file-by-field config 'zshenv))) '())
  184. ,@(if (zsh-field-not-empty? config 'zshrc)
  185. `((".zshrc" ,(zsh-file-by-field config 'zshrc))) '())
  186. ,@(if (zsh-field-not-empty? config 'zlogin)
  187. `((".zlogin" ,(zsh-file-by-field config 'zlogin))) '())
  188. ,@(if (zsh-field-not-empty? config 'zlogout)
  189. `((".zlogout" ,(zsh-file-by-field config 'zlogout))) '())))
  190. (define (add-zsh-dot-configuration config)
  191. (define zshenv-auxiliary-file
  192. (mixed-text-file
  193. "zshenv-auxiliary"
  194. "export ZDOTDIR=${XDG_CONFIG_HOME:-$HOME/.config}/zsh\n"
  195. "[[ -f $ZDOTDIR/.zshenv ]] && source $ZDOTDIR/.zshenv\n"))
  196. (if (home-zsh-configuration-xdg-flavor? config)
  197. `((".zshenv" ,zshenv-auxiliary-file))
  198. (zsh-get-configuration-files config)))
  199. (define (add-zsh-xdg-configuration config)
  200. (if (home-zsh-configuration-xdg-flavor? config)
  201. (map
  202. (lambda (lst)
  203. (cons (string-append "zsh/" (car lst))
  204. (cdr lst)))
  205. (zsh-get-configuration-files config))
  206. '()))
  207. (define (add-zsh-packages config)
  208. (list (home-zsh-configuration-package config)))
  209. (define-configuration/no-serialization home-zsh-extension
  210. (environment-variables
  211. (alist '())
  212. "Association list of environment variables to set.")
  213. (zshrc
  214. (text-config '())
  215. "List of file-like objects.")
  216. (zshenv
  217. (text-config '())
  218. "List of file-like objects.")
  219. (zprofile
  220. (text-config '())
  221. "List of file-like objects.")
  222. (zlogin
  223. (text-config '())
  224. "List of file-like objects.")
  225. (zlogout
  226. (text-config '())
  227. "List of file-like objects."))
  228. (define (home-zsh-extensions original-config extension-configs)
  229. (home-zsh-configuration
  230. (inherit original-config)
  231. (environment-variables
  232. (append (home-zsh-configuration-environment-variables original-config)
  233. (append-map
  234. home-zsh-extension-environment-variables extension-configs)))
  235. (zshrc
  236. (append (home-zsh-configuration-zshrc original-config)
  237. (append-map
  238. home-zsh-extension-zshrc extension-configs)))
  239. (zshenv
  240. (append (home-zsh-configuration-zshenv original-config)
  241. (append-map
  242. home-zsh-extension-zshenv extension-configs)))
  243. (zprofile
  244. (append (home-zsh-configuration-zprofile original-config)
  245. (append-map
  246. home-zsh-extension-zprofile extension-configs)))
  247. (zlogin
  248. (append (home-zsh-configuration-zlogin original-config)
  249. (append-map
  250. home-zsh-extension-zlogin extension-configs)))
  251. (zlogout
  252. (append (home-zsh-configuration-zlogout original-config)
  253. (append-map
  254. home-zsh-extension-zlogout extension-configs)))))
  255. (define home-zsh-service-type
  256. (service-type (name 'home-zsh)
  257. (extensions
  258. (list (service-extension
  259. home-files-service-type
  260. add-zsh-dot-configuration)
  261. (service-extension
  262. home-xdg-configuration-files-service-type
  263. add-zsh-xdg-configuration)
  264. (service-extension
  265. home-profile-service-type
  266. add-zsh-packages)))
  267. (compose identity)
  268. (extend home-zsh-extensions)
  269. (default-value (home-zsh-configuration))
  270. (description "Install and configure Zsh.")))
  271. ;;;
  272. ;;; Bash.
  273. ;;;
  274. (define (bash-serialize-aliases field-name val)
  275. #~(string-append
  276. #$@(map
  277. (match-lambda
  278. ((key . #f)
  279. "")
  280. ((key . #t)
  281. #~(string-append "alias " #$key "\n"))
  282. ((key . value)
  283. #~(string-append "alias " #$key "=\"" #$value "\"\n")))
  284. val)))
  285. (define-configuration home-bash-configuration
  286. (package
  287. (package bash)
  288. "The Bash package to use.")
  289. (guix-defaults?
  290. (boolean #t)
  291. "Add sane defaults like reading @file{/etc/bashrc} and coloring the output of
  292. @command{ls} to the top of the @file{.bashrc} file.")
  293. (environment-variables
  294. (alist '())
  295. "Association list of environment variables to set for the Bash session. The
  296. rules for the @code{home-environment-variables-service-type} apply
  297. here (@pxref{Essential Home Services}). The contents of this field will be
  298. added after the contents of the @code{bash-profile} field."
  299. (serializer serialize-posix-env-vars))
  300. (aliases
  301. (alist '())
  302. "Association list of aliases to set for the Bash session. The aliases will be
  303. defined after the contents of the @code{bashrc} field has been put in the
  304. @file{.bashrc} file. The alias will automatically be quoted, so something line
  305. this:
  306. @lisp
  307. '((\"ls\" . \"ls -alF\"))
  308. @end lisp
  309. turns into
  310. @example
  311. alias ls=\"ls -alF\"
  312. @end example"
  313. (serializer bash-serialize-aliases))
  314. (bash-profile
  315. (text-config '())
  316. "List of file-like objects, which will be added to @file{.bash_profile}.
  317. Used for executing user's commands at start of login shell (In most
  318. cases the shell started on tty just after login). @file{.bash_login}
  319. won't be ever read, because @file{.bash_profile} always present.")
  320. (bashrc
  321. (text-config '())
  322. "List of file-like objects, which will be added to @file{.bashrc}.
  323. Used for executing user's commands at start of interactive shell (The
  324. shell for interactive usage started by typing @code{bash} or by
  325. terminal app or any other program).")
  326. (bash-logout
  327. (text-config '())
  328. "List of file-like objects, which will be added to @file{.bash_logout}.
  329. Used for executing user's commands at the exit of login shell. It
  330. won't be read in some cases (if the shell terminates by exec'ing
  331. another process for example)."))
  332. (define (add-bash-configuration config)
  333. (define (filter-fields field)
  334. (filter-configuration-fields home-bash-configuration-fields
  335. (list field)))
  336. (define (serialize-field field)
  337. (serialize-configuration
  338. config
  339. (filter-fields field)))
  340. (define* (file-if-not-empty field #:optional (extra-content #f))
  341. (let ((file-name (symbol->string field))
  342. (field-obj (car (filter-fields field))))
  343. (if (or extra-content
  344. (not (null? ((configuration-field-getter field-obj) config))))
  345. `(,(string-append "." (object->snake-case-string file-name))
  346. ,(apply mixed-text-file
  347. (object->snake-case-string file-name)
  348. (append (or extra-content '())
  349. (list (serialize-field field)))))
  350. '())))
  351. (filter
  352. (compose not null?)
  353. `((".bash_profile"
  354. ,(mixed-text-file
  355. "bash_profile"
  356. "\
  357. # Set up the system, user profile, and related variables.
  358. # /etc/profile will be sourced by bash automatically
  359. # Set up the home environment profile.
  360. if [ -f ~/.profile ]; then source ~/.profile; fi
  361. # Honor per-interactive-shell startup file
  362. if [ -f ~/.bashrc ]; then source ~/.bashrc; fi
  363. "
  364. ;; The host distro might provide a bad 'PS1' default--e.g., not taking
  365. ;; $GUIX_ENVIRONMENT into account. Provide a good default here when
  366. ;; asked to. The default can be overridden below via
  367. ;; 'environment-variables'.
  368. (if (home-bash-configuration-guix-defaults? config)
  369. "PS1='\\u@\\h \\w${GUIX_ENVIRONMENT:+ [env]}\\$ '\n"
  370. "")
  371. (serialize-field 'bash-profile)
  372. (serialize-field 'environment-variables)))
  373. ,@(list (file-if-not-empty
  374. 'bashrc
  375. (if (home-bash-configuration-guix-defaults? config)
  376. (list (serialize-field 'aliases)
  377. (plain-file-content %default-bashrc))
  378. (list (serialize-field 'aliases))))
  379. (file-if-not-empty 'bash-logout)))))
  380. (define (add-bash-packages config)
  381. (list (home-bash-configuration-package config)))
  382. (define-configuration/no-serialization home-bash-extension
  383. (environment-variables
  384. (alist '())
  385. "Additional environment variables to set. These will be combined with the
  386. environment variables from other extensions and the base service to form one
  387. coherent block of environment variables.")
  388. (aliases
  389. (alist '())
  390. "Additional aliases to set. These will be combined with the aliases from
  391. other extensions and the base service.")
  392. (bash-profile
  393. (text-config '())
  394. "Additional text blocks to add to @file{.bash_profile}, which will be combined
  395. with text blocks from other extensions and the base service.")
  396. (bashrc
  397. (text-config '())
  398. "Additional text blocks to add to @file{.bashrc}, which will be combined
  399. with text blocks from other extensions and the base service.")
  400. (bash-logout
  401. (text-config '())
  402. "Additional text blocks to add to @file{.bash_logout}, which will be combined
  403. with text blocks from other extensions and the base service."))
  404. (define (home-bash-extensions original-config extension-configs)
  405. (match-record original-config <home-bash-configuration>
  406. (environment-variables aliases bash-profile bashrc bash-logout)
  407. (home-bash-configuration
  408. (inherit original-config)
  409. (environment-variables
  410. (append environment-variables
  411. (append-map
  412. home-bash-extension-environment-variables extension-configs)))
  413. (aliases
  414. (append aliases
  415. (append-map
  416. home-bash-extension-aliases extension-configs)))
  417. (bash-profile
  418. (append bash-profile
  419. (append-map
  420. home-bash-extension-bash-profile extension-configs)))
  421. (bashrc
  422. (append bashrc
  423. (append-map
  424. home-bash-extension-bashrc extension-configs)))
  425. (bash-logout
  426. (append bash-logout
  427. (append-map
  428. home-bash-extension-bash-logout extension-configs))))))
  429. (define home-bash-service-type
  430. (service-type (name 'home-bash)
  431. (extensions
  432. (list (service-extension
  433. home-files-service-type
  434. add-bash-configuration)
  435. (service-extension
  436. home-profile-service-type
  437. add-bash-packages)))
  438. (compose identity)
  439. (extend home-bash-extensions)
  440. (default-value (home-bash-configuration))
  441. (description "Install and configure GNU Bash.")))
  442. ;;;
  443. ;;; Fish.
  444. ;;;
  445. (define (serialize-fish-aliases field-name val)
  446. #~(string-append
  447. #$@(map (match-lambda
  448. ((key . value)
  449. #~(string-append "alias " #$key " \"" #$value "\"\n"))
  450. (_ ""))
  451. val)))
  452. (define (serialize-fish-abbreviations field-name val)
  453. #~(string-append
  454. #$@(map (match-lambda
  455. ((key . value)
  456. #~(string-append "abbr --add " #$key " " #$value "\n"))
  457. (_ ""))
  458. val)))
  459. (define (serialize-fish-env-vars field-name val)
  460. #~(string-append
  461. #$@(map (match-lambda
  462. ((key . #f)
  463. "")
  464. ((key . #t)
  465. #~(string-append "set -x " #$key "\n"))
  466. ((key . value)
  467. #~(string-append "set -x " #$key " " #$value "\n")))
  468. val)))
  469. (define-configuration home-fish-configuration
  470. (package
  471. (package fish)
  472. "The Fish package to use.")
  473. (config
  474. (text-config '())
  475. "List of file-like objects, which will be added to
  476. @file{$XDG_CONFIG_HOME/fish/config.fish}.")
  477. (environment-variables
  478. (alist '())
  479. "Association list of environment variables to set in Fish."
  480. (serializer serialize-fish-env-vars))
  481. (aliases
  482. (alist '())
  483. "Association list of aliases for Fish, both the key and the value
  484. should be a string. An alias is just a simple function that wraps a
  485. command, If you want something more akin to @dfn{aliases} in POSIX
  486. shells, see the @code{abbreviations} field."
  487. (serializer serialize-fish-aliases))
  488. (abbreviations
  489. (alist '())
  490. "Association list of abbreviations for Fish. These are words that,
  491. when typed in the shell, will automatically expand to the full text."
  492. (serializer serialize-fish-abbreviations)))
  493. (define (fish-files-service config)
  494. `(("fish/config.fish"
  495. ,(mixed-text-file
  496. "fish-config.fish"
  497. #~(string-append "\
  498. # if we haven't sourced the login config, do it
  499. status --is-login; and not set -q __fish_login_config_sourced
  500. and begin
  501. set --prepend fish_function_path "
  502. #$fish-foreign-env
  503. "/share/fish/functions
  504. fenv source $HOME/.profile
  505. set -e fish_function_path[1]
  506. set -g __fish_login_config_sourced 1
  507. end\n\n")
  508. (serialize-configuration
  509. config
  510. home-fish-configuration-fields)))))
  511. (define (fish-profile-service config)
  512. (list (home-fish-configuration-package config)))
  513. (define-configuration/no-serialization home-fish-extension
  514. (config
  515. (text-config '())
  516. "List of file-like objects for extending the Fish initialization file.")
  517. (environment-variables
  518. (alist '())
  519. "Association list of environment variables to set.")
  520. (aliases
  521. (alist '())
  522. "Association list of Fish aliases.")
  523. (abbreviations
  524. (alist '())
  525. "Association list of Fish abbreviations."))
  526. (define (home-fish-extensions original-config extension-configs)
  527. (home-fish-configuration
  528. (inherit original-config)
  529. (config
  530. (append (home-fish-configuration-config original-config)
  531. (append-map
  532. home-fish-extension-config extension-configs)))
  533. (environment-variables
  534. (append (home-fish-configuration-environment-variables original-config)
  535. (append-map
  536. home-fish-extension-environment-variables extension-configs)))
  537. (aliases
  538. (append (home-fish-configuration-aliases original-config)
  539. (append-map
  540. home-fish-extension-aliases extension-configs)))
  541. (abbreviations
  542. (append (home-fish-configuration-abbreviations original-config)
  543. (append-map
  544. home-fish-extension-abbreviations extension-configs)))))
  545. ;; TODO: Support for generating completion files
  546. ;; TODO: Support for installing plugins
  547. (define home-fish-service-type
  548. (service-type (name 'home-fish)
  549. (extensions
  550. (list (service-extension
  551. home-xdg-configuration-files-service-type
  552. fish-files-service)
  553. (service-extension
  554. home-profile-service-type
  555. fish-profile-service)))
  556. (compose identity)
  557. (extend home-fish-extensions)
  558. (default-value (home-fish-configuration))
  559. (description "\
  560. Install and configure Fish, the friendly interactive shell.")))
  561. (define (generate-home-shell-profile-documentation)
  562. (generate-documentation
  563. `((home-shell-profile-configuration
  564. ,home-shell-profile-configuration-fields))
  565. 'home-shell-profile-configuration))
  566. (define (generate-home-bash-documentation)
  567. (string-append
  568. (generate-documentation
  569. `((home-bash-configuration
  570. ,home-bash-configuration-fields))
  571. 'home-bash-configuration)
  572. "\n\n"
  573. (generate-documentation
  574. `((home-bash-extension
  575. ,home-bash-extension-fields))
  576. 'home-bash-extension)))
  577. (define (generate-home-zsh-documentation)
  578. (generate-documentation
  579. `((home-zsh-configuration
  580. ,home-zsh-configuration-fields))
  581. 'home-zsh-configuration))
  582. (define (generate-home-fish-documentation)
  583. (string-append
  584. (generate-documentation
  585. `((home-fish-configuration
  586. ,home-fish-configuration-fields))
  587. 'home-fish-configuration)
  588. "\n\n"
  589. (generate-documentation
  590. `((home-fish-extension
  591. ,home-fish-extension-fields))
  592. 'home-fish-extension)))