summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnaud Daby-Seesaram <ds-ac@nanein.fr>2024-10-09 00:33:41 +0200
committerFlorian Pelz <pelzflorian@pelzflorian.de>2024-10-12 14:26:01 +0200
commitb64f7984a5e2aba04df72a92f0044e423efe77c6 (patch)
tree6f7dd897f6924757ec9663935e2913443ba91c86
parentb9ec6251bee8e4e500eb9291087fbf2018aca113 (diff)
home: services: Add 'home-sway-service-type'.
* gnu/home/services/sway.scm: New file. (home-sway-service-type): New variable. (sway-configuration->file): New procedure. (sway-configuration): New configuration record. (sway-bar): New configuration record. (sway-output): New configuration record. (sway-input): New configuration record. (point): New configuration record. (sway-color): New configuration record. (sway-border-color): New configuration record. (sway-mode): New configuration record. (flatmap): New procedure. * gnu/local.mk: Add gnu/home/services/sway.scm. * doc/guix.texi (Sway window manager): New node to document the above changes. Signed-off-by: Florian Pelz <pelzflorian@pelzflorian.de> Change-Id: I880261570c5afdb795f2ce18bac2b9a5c898677f
-rw-r--r--doc/guix.texi406
-rw-r--r--gnu/home/services/sway.scm870
-rw-r--r--gnu/local.mk1
3 files changed, 1277 insertions, 0 deletions
diff --git a/doc/guix.texi b/doc/guix.texi
index 8f3b8ef6cdd..ddbff8bc235 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -130,6 +130,7 @@ Copyright @copyright{} 2024 Richard Sent@*
130Copyright @copyright{} 2024 Dariqq@* 130Copyright @copyright{} 2024 Dariqq@*
131Copyright @copyright{} 2024 Denis 'GNUtoo' Carikli@* 131Copyright @copyright{} 2024 Denis 'GNUtoo' Carikli@*
132Copyright @copyright{} 2024 Fabio Natali@* 132Copyright @copyright{} 2024 Fabio Natali@*
133Copyright @copyright{} 2024 Arnaud Daby-Seesaram@*
133 134
134Permission is granted to copy, distribute and/or modify this document 135Permission is granted to copy, distribute and/or modify this document
135under the terms of the GNU Free Documentation License, Version 1.3 or 136under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -460,6 +461,7 @@ Home Services
460* Mail: Mail Home Services. Services for managing mail. 461* Mail: Mail Home Services. Services for managing mail.
461* Messaging: Messaging Home Services. Services for managing messaging. 462* Messaging: Messaging Home Services. Services for managing messaging.
462* Media: Media Home Services. Services for managing media. 463* Media: Media Home Services. Services for managing media.
464* Sway: Sway window manager. Setting up the Sway configuration.
463* Networking: Networking Home Services. Networking services. 465* Networking: Networking Home Services. Networking services.
464* Miscellaneous: Miscellaneous Home Services. More services. 466* Miscellaneous: Miscellaneous Home Services. More services.
465 467
@@ -45210,6 +45212,7 @@ services)}.
45210* Mail: Mail Home Services. Services for managing mail. 45212* Mail: Mail Home Services. Services for managing mail.
45211* Messaging: Messaging Home Services. Services for managing messaging. 45213* Messaging: Messaging Home Services. Services for managing messaging.
45212* Media: Media Home Services. Services for managing media. 45214* Media: Media Home Services. Services for managing media.
45215* Sway: Sway window manager. Setting up the Sway configuration.
45213* Networking: Networking Home Services. Networking services. 45216* Networking: Networking Home Services. Networking services.
45214* Miscellaneous: Miscellaneous Home Services. More services. 45217* Miscellaneous: Miscellaneous Home Services. More services.
45215@end menu 45218@end menu
@@ -47124,6 +47127,409 @@ kodi} for more information.
47124@end table 47127@end table
47125@end deftp 47128@end deftp
47126 47129
47130@node Sway window manager
47131@subsection Sway window manager
47132
47133@cindex sway, Home Service
47134@cindex sway, configuration
47135The @code{(gnu home services sway)} module provides
47136@code{home-sway-service-type}, a home service to configure the
47137@uref{https://github.com/swaywm/sway,Sway window manager for Wayland} in
47138a declarative way.
47139
47140Here is an example of a service and its configuration that you could add
47141to the @code{services} field of your @code{home-environment}:
47142
47143@lisp
47144(service home-sway-service-type
47145 (sway-configuration
47146 (gestures
47147 '((swipe:3:down . "move to scratchpad")
47148 (swipe:3:up . "scratchpad show")))
47149 (outputs
47150 (list (sway-output
47151 (identifier '*)
47152 (background (file-append sway
47153 "\
47154/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png")))))))
47155@end lisp
47156
47157The above example describes a Sway configuration in which
47158@itemize
47159@item
47160all monitors use a particular wallpaper whose @file{.png} is provided by
47161the @code{sway} package;
47162@item
47163swiping down (resp.@: up) with three fingers moves the active window to
47164the scratchpad (resp.@: shows/hides the scratchpad).
47165@end itemize
47166
47167@quotation Note
47168This home service only sets up the configuration file and profile
47169packages for Sway. It does @emph{not} start Sway in any way. If you
47170want to do so, you might be interested in using
47171@code{greetd-wlgreet-sway-session} instead.
47172
47173The proceedure @code{sway-configuration->file} defined below can be used
47174to provide the value for the @emph{optional} @code{sway-configuration}
47175field of @code{greetd-wlgreet-sway-session}.
47176@end quotation
47177
47178@deffn {Procedure} sway-configuration->file config
47179This procedure takes one argument @code{config}, which must be a
47180@code{sway-configuration} record (defined below), and returns a
47181file-like object representing the serialized configuration.
47182@end deffn
47183
47184@defvar home-sway-service-type
47185This is a home service type to set up Sway. It takes care of:
47186@itemize
47187@item
47188providing a @file{~/.config/sway/config} file,
47189@item
47190adding Sway-related packages to your profile.
47191@end itemize
47192@end defvar
47193
47194@deftp {Data Type} sway-configuration
47195This configuration record describes the Sway configuration
47196(see@ @cite{sway(5)}). Available fields are:
47197
47198@table @asis
47199@item @code{variables} (default: @code{%sway-default-variables})
47200The value of this field is an association list in which keys are symbols
47201and values are either strings, G-expressions or file-like objects
47202(@pxref{G-Expressions}).
47203
47204Example:
47205@lisp
47206(variables `((mod . "Mod4") ; string
47207 (term ; file-append
47208 . ,(file-append foot "/bin/foot"))
47209 (Term ; G-expression
47210 . ,#~(string-append #$foot "/bin/foot"))))
47211@end lisp
47212
47213@quotation Note
47214Default keybindings assume the existence of variables named @code{$mod},
47215@code{$left}, @code{$right}, @code{$up} and @code{$down}. If you choose
47216not to define these variables, make sure to remove keybindings referring
47217to them.
47218@end quotation
47219
47220@item @code{keybindings} (default: @code{%sway-default-keybindings})
47221This field describes keybindings for the @emph{default} mode. The value
47222is an association list: keys are symbols and values are either strings
47223or G-expressions.
47224
47225The following snippet launches the terminal when pressing @kbd{$mod+t}
47226and @kbd{$mod+Shift+t} (assuming that a variable @code{$term} is
47227defined):
47228@lisp
47229`(($mod+t . ,#~(string-append "exec " #$foot "/bin/foot"))
47230 ($mod+Shift+t . "exec $term"))
47231@end lisp
47232
47233@item @code{gestures} (default: @code{%sway-default-gestures})
47234Similar to the previous field, but for finger-gestures.
47235
47236The following snippet allows to navigate through workspaces by swiping
47237right and left with three fingers:
47238@lisp
47239'((swipe:3:right . "workspace next_on_output")
47240 (swipe:3:left . "workspace prev_on_output"))
47241@end lisp
47242
47243@item @code{packages} (default: @code{%sway-default-packages})
47244This field describes a list of packages to add to the user profile. At
47245the moment, the default value only adds @code{sway} to the profile.
47246
47247@item @code{inputs} (default: @code{'()})
47248List of @code{sway-input} configuration records (described below).
47249
47250@item @code{outputs} (default: @code{'()})
47251List of @code{sway-output} configuration records (described below).
47252
47253@item @code{bar} (optional @code{sway-bar} record)
47254Optional @code{sway-bar} record (described below) to configure a Sway
47255bar.
47256
47257@item @code{modes} (default: @code{%sway-default-modes})
47258List of @code{sway-mode} records (described below) to add modes to the
47259Sway configuration. The default value @code{%sway-default-modes} adds
47260the ``resize'' mode of the default Sway configuration (as described
47261below).
47262
47263@item @code{startup+reload-programs} (default: @code{'()})
47264Programs to execute at startup time @emph{and} after every configuration
47265reload. The value of this field is a list of strings, G-expressions or
47266file-like objects (@pxref{G-Expressions}).
47267
47268@item @code{startup-programs} (default: @code{%sway-default-execs})
47269Programs to execute at startup time. As above, values of this field are
47270a list of strings, G-expressions or file-like objects.
47271
47272The default value, @code{%sway-default-execs}, executes @code{swayidle}
47273in order to lock the screen after 5@ minutes of inactivity (displaying a
47274background distributed with Sway) and turn the screen off after 10@
47275minutes of inactivity.
47276
47277@item @code{extra-content} (default: @code{'()})
47278Lines to add to the configuration file. The value of this field is a
47279list of strings or G-expressions.
47280@end table
47281@end deftp
47282
47283@deftp {Data Type} sway-input
47284@code{sway-input} records describe input blocks (see@
47285@cite{sway-input(5)}). For example, the following snippet makes all
47286keyboards use a French layout, in which @kbd{capslock} has been remapped
47287to @kbd{ctrl}:
47288@lisp
47289(sway-input (identifier "type:keyboard")
47290 (layout
47291 (keyboard-layout "fr" #:options '("ctrl:nocaps"))))
47292@end lisp
47293
47294Available fields for @code{sway-input} configuration records are:
47295
47296@table @asis
47297@item @code{identifier} (default: @code{'*})
47298Identifier of the input. The field accepts symbols and strings. If the
47299@code{identifier} is a symbol, it is inserted as is; if it is a string,
47300it will be quoted in the configuration file.
47301
47302@item @code{layout} (optional @code{<keyboard-layout>} record)
47303Keyboard specific option. Field specifying the layout to use for the
47304input. The value must be a @code{<keyboard-layout>} record
47305(@pxref{Keyboard Layout}).
47306
47307@quotation Note
47308@code{(gnu home services sway)} does not re-export the
47309@code{keyboard-layout} procedure.
47310@end quotation
47311
47312@item @code{disable-while-typing} (optional boolean)
47313If @code{#t} (resp.@: @code{#f}) enables (resp.@: disables) the
47314``disable while typing'' option for this input.
47315
47316@item @code{disable-while-trackpointing} (optional boolean)
47317If @code{#t} (resp.@: @code{#f}), enables (resp.@: disables) the
47318``disable while track-pointing'' option for this input.
47319
47320@item @code{tap} (optional boolean)
47321Enables or disables the ``tap'' option, which allows clicking by tapping
47322on a touchpad.
47323
47324@item @code{extra-content} (default: @code{'()})
47325Lines to add to the input block. The value of this field must a list
47326whose elements are either strings or G-expressions.
47327@end table
47328@end deftp
47329
47330@deftp {Data Type} sway-output
47331@code{sway-output} records describe Sway outputs (see@
47332@cite{sway-output(5)}). Available fields are:
47333
47334@table @asis
47335@item @code{identifier} (default: @code{'*})
47336Identifier of the monitor. The field accepts symbols and strings. If
47337the @code{identifier} is a symbol, it is inserted as is; if it is a
47338string, it will be quoted in the configuration file.
47339
47340@item @code{resolution} (optional string)
47341This string defines the resolution of the monitor.
47342
47343@item @code{position} (optional)
47344The (optional) value of this field must be a @code{point}.
47345Example:
47346@lisp
47347(position
47348 (point (x 1920)
47349 (y 0)))
47350@end lisp
47351
47352@item @code{background} (optional)
47353The value of this field describes what wallpaper to use on this output.
47354The field accepts the following types of values:
47355@itemize
47356@item
47357a string,
47358@item
47359a G-expression,
47360@item
47361a file-like object,
47362@item
47363a pair. The first argument of this pair must be a string, a
47364G-expression or a file-like object. The second element describes how
47365the wallpaper will be displayed. It must be a symbol among
47366@code{stretch}, @code{fill}, @code{fit}, @code{center} and @code{tile}.
47367
47368If the second element is not specified (@i{i.e.}@: when the value is not
47369a pair), the @code{fill} mode will be used.
47370@end itemize
47371
47372@quotation Note
47373In order to use an SVG file, you must have @code{librsvg} in your
47374profile (@i{e.g.}@: by adding it in the @code{packages} field of
47375@code{sway-configuration}).
47376@end quotation
47377
47378@item @code{extra-content} (default: @code{'()})
47379List defining additional lines to add to the output configuration block.
47380Elements of the list must be either strings or G-expressions.
47381@end table
47382@end deftp
47383
47384@deftp {Data Type} sway-border-color
47385@table @code
47386@item border
47387Color of the border.
47388@item background
47389Color of the background.
47390@item text
47391Color of the text.
47392@end table
47393@end deftp
47394
47395@deftp {Data Type} sway-color
47396@table @asis
47397@item @code{background} (optional string)
47398Background color of the bar.
47399
47400@item @code{statusline} (optional string)
47401Text color of the status line.
47402
47403@item @code{focused-background} (optional string)
47404Background color of the bar on the currently focused monitor.
47405
47406@item @code{focused-statusline} (optional string)
47407Text color of the statusline on the currently focused monitor.
47408
47409@item @code{focused-workspace} (optional @code{sway-border-color})
47410Color scheme for focused workspaces.
47411
47412@item @code{active-workspace} (optional @code{sway-border-color})
47413Color scheme for active workspaces.
47414
47415@item @code{inactive-workspace} (optional @code{sway-border-color})
47416Color scheme for inactive workspaces.
47417
47418@item @code{urgent-workspace} (optional @code{sway-border-color})
47419Color scheme for workspaces containing ``urgent windows''.
47420
47421@item @code{binding-mode} (optional @code{sway-border-color})
47422Color scheme for the binding mode indicator.
47423@end table
47424@end deftp
47425
47426@deftp {Data Type} sway-bar
47427Describes the Sway bar (see@ @cite{sway-bar(5)}).
47428
47429@table @asis
47430@item @code{identifier} (default: @code{'bar0})
47431Identifier of the bar. The value must be a symbol.
47432
47433@item @code{position} (optional)
47434Specify the position of the bar. Accepted values are @code{'top} or
47435@code{'bottom}.
47436
47437@item @code{hidden-state} (optional)
47438Specify the apparence of the bar when it is hidden. Accepted values are
47439@code{'hide} or @code{'show}.
47440
47441@item @code{binding-mode-indicator} (optional)
47442Boolean enabling or disabling the binding mode indicator.
47443
47444@item @code{colors} (optional)
47445An optional @code{sway-color} configuration record.
47446
47447@item @code{status-command} (optional)
47448This field accept strings, G-expressions and executable file-like
47449values. The default value is a command (string) that prints the date
47450and time every second.
47451
47452Each line printed on @code{stdout} by this command (or script) will be
47453displayed on the status area of the bar.
47454
47455Below are a few examples using:
47456@itemize
47457@item
47458a string: @code{"while date +'%Y-%m-%d %X'; do sleep 1; done"},
47459@item
47460a G-exp:
47461@lisp
47462#~(string-append "while "
47463 #$coreutils "/bin/date"
47464 " +'%Y-%m-%d %X'; do sleep 1; done")
47465@end lisp
47466@item
47467an executable file:
47468@lisp
47469(program-file
47470 "sway-bar-status"
47471 #~(begin
47472 (use-modules (ice-9 format)
47473 (srfi srfi-19))
47474 (let loop ()
47475 (let* ((date (date->string
47476 (current-date)
47477 "~d/~m/~Y (~a) • ~H:~M:~S")))
47478 (format #t "~a~%~!" date)
47479 (sleep 1)
47480 (loop)))))
47481@end lisp
47482@end itemize
47483
47484@item @code{mouse-bindings} (default: @code{'()})
47485This field accepts an associative list. Keys are integers describing
47486mouse events. Values can either be strings or G-expressions.
47487
47488The module @code{(gnu home services sway)} exports constants
47489@code{%ev-code-mouse-left}, @code{%ev-code-mouse-right} and
47490@code{%ev-code-mouse-scroll-click} whose values are integers
47491corresponding to left, right and scroll click respectively. For
47492example, with @code{(mouse-bindings `((,%ev-code-mouse-left . "exec
47493$term")))}, left clicks in the status bar open the terminal (assuming
47494that the variable @code{$term} is bound to a terminal).
47495@end table
47496@end deftp
47497
47498@deftp {Data Type} sway-mode
47499Describes a Sway mode (see@ @cite{sway(5)}). For example, the following
47500snippet defines the resize mode of the default Sway configuration:
47501@example
47502(sway-mode
47503 (mode-name "resize")
47504 (keybindings
47505 '(($left . "resize shrink width 10px")
47506 ($right . "resize grow width 10px")
47507 ($down . "resize grow height 10px")
47508 ($up . "resize shrink height 10px")
47509 (Left . "resize shrink width 10px")
47510 (Right . "resize grow width 10px")
47511 (Down . "resize grow height 10px")
47512 (Up . "resize shrink height 10px")
47513 (Return . "mode \"default\"")
47514 (Escape . "mode \"default\""))))
47515@end example
47516
47517@table @asis
47518@item @code{mode-name} (default: @code{"default"})
47519Name of the mode. This field accepts strings.
47520
47521@item @code{keybindings} (default: @code{'()})
47522This field describes keybindings. The value is an association list:
47523keys are symbols and values are either strings or G-expressions, as
47524above.
47525
47526@item @code{mouse-bindings} (default: @code{'()})
47527Ditto, but keys are mouse events (integers). Constants
47528@code{%ev-code-mouse-*} described above can be used as helpers to define
47529mouse bindings.
47530@end table
47531@end deftp
47532
47127@node Networking Home Services 47533@node Networking Home Services
47128@subsection Networking Home Services 47534@subsection Networking Home Services
47129 47535
diff --git a/gnu/home/services/sway.scm b/gnu/home/services/sway.scm
new file mode 100644
index 00000000000..0e1a2d57b2a
--- /dev/null
+++ b/gnu/home/services/sway.scm
@@ -0,0 +1,870 @@
1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2024 Arnaud Daby-Seesaram <ds-ac@nanein.fr>
3;;;
4;;; This file is part of GNU Guix.
5;;;
6;;; GNU Guix is free software; you can redistribute it and/or modify it
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
11;;; GNU Guix is distributed in the hope that it will be useful, but
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
18
19(define-module (gnu home services sway)
20 #:use-module (guix modules)
21 #:use-module (guix gexp)
22 #:use-module (srfi srfi-1)
23 #:use-module (ice-9 match)
24 #:use-module (guix packages)
25 #:use-module (gnu system keyboard)
26 #:use-module (gnu services configuration)
27 #:use-module (gnu home services)
28 #:use-module (gnu packages wm)
29 #:use-module (gnu packages terminals)
30 #:export (;; Event codes
31 %ev-code-mouse-left
32 %ev-code-mouse-right
33 %ev-code-mouse-scroll-click
34
35 ;; Configuration records.
36 sway-configuration
37 sway-bar
38 sway-output
39 sway-input
40 point
41 sway-color
42 sway-border-color
43 home-sway-service-type
44 sway-configuration->file
45 sway-mode
46
47 ;; Default values.
48 %sway-default-variables
49 %sway-default-gestures
50 %sway-default-modes
51 %sway-default-keybindings
52 %sway-default-startup-programs
53 %sway-default-packages))
54
55;; Helper function.
56(define (flatmap f l)
57 (let loop ((lst (reverse l)) (acc '()))
58 (match lst
59 (() acc)
60 ((head . tail)
61 (let* ((h (f head))
62 (acc (append h acc)))
63 (loop tail acc))))))
64
65
66;;;
67;;; Definition of configurations.
68;;;
69
70(define (string-ish? s)
71 (or (gexp? s)
72 (file-like? s)
73 (string? s)))
74
75(define (string-or-gexp? s)
76 (or (gexp? s)
77 (string? s)))
78
79(define (list-of-string-ish? lst)
80 (every string-ish? lst))
81
82(define (list-of-packages? lst)
83 (every package? lst))
84
85(define (bar-position? p)
86 (member p '(top bottom)))
87
88(define (hidden-state? st)
89 (member st '(hide show)))
90
91(define (string-or-symbol? s)
92 (or (string? s)
93 (symbol? s)))
94
95(define (strings? lst)
96 (every string? lst))
97
98(define (extra-content? extra)
99 (every string-or-gexp? extra))
100
101(define (make-alist-predicate key? val?)
102 (lambda (lst)
103 (every
104 (lambda (item)
105 (match item
106 ((k . v)
107 (and (key? k)
108 (val? v)))
109 (_ #f)))
110 lst)))
111
112(define bindings?
113 (make-alist-predicate symbol? string-or-gexp?))
114
115(define mouse-bindings?
116 (make-alist-predicate integer? string-or-gexp?))
117
118(define (variables? lst)
119 (make-alist-predicate symbol? string-ish?))
120
121(define-maybe string (no-serialization))
122(define-maybe strings (no-serialization))
123(define-maybe boolean (no-serialization))
124(define-maybe keyboard-layout (no-serialization))
125
126(define-configuration/no-serialization sway-input
127 (identifier
128 (string-or-symbol '*)
129 "Identifier of the input.")
130 (layout
131 maybe-keyboard-layout
132 "Keyboard layout of the input.")
133 (disable-while-typing
134 maybe-boolean
135 "If `#t', disable the input while typing; if `#f' do not.")
136 (disable-while-trackpointing
137 maybe-boolean
138 "If `#t', disable the input while using a trackpoint; if `#f' do not.")
139 (tap
140 maybe-boolean
141 "Enable or disable tap.")
142 (extra-content
143 (extra-content '())
144 "Lines to add at the end of the configuration file."))
145
146(define (sway-inputs? lst)
147 (every sway-input? lst))
148
149(define-configuration/no-serialization sway-border-color
150 (border
151 string
152 "Border color.")
153 (background
154 string
155 "Background color.")
156 (text
157 string
158 "Text color."))
159
160(define-maybe sway-border-color (no-serialization))
161
162(define-configuration/no-serialization sway-color
163 (background
164 maybe-string
165 "Background color of the bar.")
166 (statusline
167 maybe-string
168 "Text color of the status line.")
169 (focused-background
170 maybe-string
171 "Background color of the bar on the currently focused monitor.")
172 (focused-statusline
173 maybe-string
174 "Text color of the statusline on the currently focused monitor.")
175 (focused-workspace
176 maybe-sway-border-color
177 "Color scheme for focused workspaces.")
178 (active-workspace
179 maybe-sway-border-color
180 "Color scheme for active workspaces.")
181 (inactive-workspace
182 maybe-sway-border-color
183 "Color scheme for inactive workspaces.")
184 (urgent-workspace
185 maybe-sway-border-color
186 "Color scheme for workspaces containing `urgent' windows.")
187 (binding-mode
188 maybe-sway-border-color
189 "Color scheme for the binding mode indicator."))
190
191(define-maybe sway-color (no-serialization))
192
193(define (status-command? c)
194 (or (string? c)
195 (file-like? c)
196 (gexp? c)))
197
198(define-maybe bar-position (no-serialization))
199(define-maybe hidden-state (no-serialization))
200(define-maybe status-command (no-serialization))
201
202(define-configuration/no-serialization sway-bar
203 (identifier
204 (symbol 'bar0)
205 "Identifier of the bar.")
206 (position
207 maybe-bar-position
208 "Position of the bar.")
209 (hidden-state
210 maybe-hidden-state
211 "Hidden state.")
212 (binding-mode-indicator
213 maybe-boolean
214 "Binding indicator.")
215 (colors
216 maybe-sway-color
217 "Color palette of the bar.")
218 (status-command
219 maybe-status-command
220 "Status command.")
221 (mouse-bindings
222 (mouse-bindings '())
223 "Actions triggered by mouse events.")
224 (extra-content
225 (extra-content '())
226 "Extra configuration lines."))
227
228(define-maybe sway-bar (no-serialization))
229
230(define-configuration/no-serialization point
231 (x integer "X coordinate.")
232 (y integer "Y coordinate."))
233
234(define-maybe point (no-serialization))
235
236(define (background? bg)
237 (or (string-ish? bg)
238 (and (pair? bg)
239 (string-ish? (car bg))
240 (member (cdr bg) '(stretch fill fit center tile)))))
241
242(define-maybe background (no-serialization))
243
244(define-configuration/no-serialization sway-output
245 (identifier
246 (string-or-symbol '*)
247 "Identifier of the output.")
248 (resolution
249 maybe-string
250 "Mode of the monitor.")
251 (position
252 maybe-point
253 "Position of the monitor.")
254 (background
255 maybe-background
256 "Background image.")
257 (extra-content
258 (extra-content '())
259 "Extra lines."))
260
261(define (sway-outputs? lst)
262 (every sway-output? lst))
263
264(define-configuration/no-serialization sway-mode
265 (mode-name
266 (string "default")
267 "Name of the mode.")
268 (keybindings
269 (bindings '())
270 "Keybindings.")
271 (mouse-bindings
272 (mouse-bindings '())
273 "Mouse bindings."))
274
275(define (sway-modes? lst)
276 (every sway-mode? lst))
277
278(define-configuration/no-serialization sway-configuration
279 (keybindings
280 (bindings %sway-default-keybindings)
281 "Keybindings.")
282 (gestures
283 (bindings %sway-default-gestures)
284 "Gestures.")
285 (packages
286 (list-of-packages
287 %sway-default-packages)
288 "List of packages to add to the profile.")
289 (variables
290 (variables %sway-default-variables)
291 "Variables declared at the beginning of the file.")
292 (inputs
293 (sway-inputs '())
294 "Inputs.")
295 (outputs
296 (sway-outputs '())
297 "Outputs.")
298 (bar
299 maybe-sway-bar
300 "Bar configuration.")
301 (modes
302 (sway-modes %sway-default-modes)
303 "Additional modes.")
304 (startup+reload-programs
305 (list-of-string-ish '())
306 "Programs to execute at startup time.")
307 (startup-programs
308 (list-of-string-ish %sway-default-startup-programs)
309 "Programs to execute at startup time.")
310 (extra-content
311 (extra-content '())
312 "Lines to add at the end of the configuration file."))
313
314
315;;;
316;;; Default settings and useful constants.
317;;;
318
319(define sway-menu
320 (program-file
321 "sway-menu.scm"
322 (with-imported-modules
323 (source-module-closure '((guix build utils)))
324 #~(begin
325 (use-modules (ice-9 ftw)
326 (ice-9 popen)
327 (ice-9 receive)
328 (ice-9 rdelim)
329 (guix build utils)
330 (srfi srfi-1))
331
332 (define (directory->files dir)
333 (define (executable-file? f)
334 ;; Cf. `(@ (guix build utils) executable-file?)' for an
335 ;; explanation of `(zero? ...)'.
336 (and=> (and (not (eq? (string-ref f 0) #\.))
337 (stat f))
338 (lambda (s)
339 (not (or
340 (zero? (logand (stat:mode s) #o100))
341 (eq? (stat:type s) 'directory))))))
342 (with-directory-excursion dir
343 (scandir "." executable-file?)))
344
345 (let ((path (string-append (getenv "HOME")
346 "/.guix-home/profile/bin"))
347 (wmenu #$(file-append wmenu "/bin/wmenu"))
348 (swaymsg #$(file-append sway "/bin/swaymsg")))
349 (receive (from to pids)
350 (pipeline `((,wmenu)))
351 (for-each
352 (lambda (c) (format to "~a~%" c))
353 (directory->files path))
354 (close to)
355 (let ((choice (read-line from)))
356 (close from)
357 (waitpid (first pids))
358 (when (string? choice) ;do not attempt to launch if no choice
359 ;was given (e.g. if Escape is pressed in
360 ;wmenu).
361 (execl swaymsg swaymsg "exec" "--"
362 choice)))))))))
363
364(define %ev-code-mouse-left 272)
365(define %ev-code-mouse-right 273)
366(define %ev-code-mouse-scroll-click 274)
367
368(define %sway-default-modes
369 (list (sway-mode
370 (mode-name "resize")
371 (keybindings
372 '(($left . "resize shrink width 10px")
373 ($down . "resize grow height 10px")
374 ($up . "resize shrink height 10px")
375 ($right . "resize grow width 10px")
376 (Left . "resize shrink width 10px")
377 (Down . "resize grow height 10px")
378 (Up . "resize shrink height 10px")
379 (Right . "resize grow width 10px")
380 (Return . "mode \"default\"")
381 (Escape . "mode \"default\""))))))
382
383(define %sway-default-packages
384 (list sway))
385
386(define %sway-default-variables
387 `((mod . "Mod4")
388 (left . "h")
389 (down . "j")
390 (up . "k")
391 (right . "l")
392 (term . ,(file-append foot "/bin/foot"))
393 (menu . ,sway-menu)))
394
395(define %sway-default-gestures
396 '((swipe:3:right . "workspace next_on_output")
397 (swipe:3:left . "workspace prev_on_output")
398 (swipe:3:down . "move to scratchpad")
399 (swipe:3:up . "scratchpad show")))
400
401(define %sway-default-keybindings
402 `(($mod+Return . "exec $term")
403 ($mod+Shift+q . "kill")
404 ($mod+d . "exec $menu")
405 ($mod+Shift+c . "reload")
406 ($mod+Shift+e
407 . ,#~(string-append
408 "exec " #$sway "/bin/swaynag -t warning -m \\\n "
409 "'You pressed the exit shortcut. Do you really want to exit sway?"
410 " This will end your Wayland session.' \\\n "
411 "-B 'Yes, exit sway' \\\n '"
412 #$sway "/bin/swaymsg exit'"))
413 ($mod+$left . "focus left")
414 ($mod+$down . "focus down")
415 ($mod+$up . "focus up")
416 ($mod+$right . "focus right")
417 ($mod+Left . "focus left")
418 ($mod+Down . "focus down")
419 ($mod+Up . "focus up")
420 ($mod+Right . "focus right")
421 ($mod+Shift+$left . "move left")
422 ($mod+Shift+$down . "move down")
423 ($mod+Shift+$up . "move up")
424 ($mod+Shift+$right . "move right")
425 ($mod+Shift+Left . "move left")
426 ($mod+Shift+Down . "move down")
427 ($mod+Shift+Up . "move up")
428 ($mod+Shift+Right . "move right")
429 ($mod+1 . "workspace number 1")
430 ($mod+2 . "workspace number 2")
431 ($mod+3 . "workspace number 3")
432 ($mod+4 . "workspace number 4")
433 ($mod+5 . "workspace number 5")
434 ($mod+6 . "workspace number 6")
435 ($mod+7 . "workspace number 7")
436 ($mod+8 . "workspace number 8")
437 ($mod+9 . "workspace number 9")
438 ($mod+0 . "workspace number 10")
439 ($mod+Shift+1 . "move container to workspace number 1")
440 ($mod+Shift+2 . "move container to workspace number 2")
441 ($mod+Shift+3 . "move container to workspace number 3")
442 ($mod+Shift+4 . "move container to workspace number 4")
443 ($mod+Shift+5 . "move container to workspace number 5")
444 ($mod+Shift+6 . "move container to workspace number 6")
445 ($mod+Shift+7 . "move container to workspace number 7")
446 ($mod+Shift+8 . "move container to workspace number 8")
447 ($mod+Shift+9 . "move container to workspace number 9")
448 ($mod+Shift+0 . "move container to workspace number 10")
449 ($mod+b . "splith")
450 ($mod+v . "splitv")
451 ($mod+s . "layout stacking")
452 ($mod+w . "layout tabbed")
453 ($mod+e . "layout toggle split")
454 ($mod+f . "fullscreen")
455 ($mod+Shift+space . "floating toggle")
456 ($mod+space . "focus mode_toggle")
457 ($mod+a . "focus parent")
458 ($mod+Shift+minus . "move scratchpad")
459 ($mod+minus . "scratchpad show")
460 ($mod+r . "mode \"resize\"")))
461
462(define %sway-default-startup-programs
463 (list
464 #~(string-append
465 #$swayidle "/bin/swayidle -w \\\n "
466 ;; 300: lock screen.
467 "timeout 300 '" #$swaylock "/bin/swaylock "
468 "--indicator-radius 75 \\\n "
469 "-i " #$sway
470 "/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png \\\n "
471 "-f -c 000000' \\\n "
472 ;; 600: lock + screen off.
473 "timeout 600 '" #$sway "/bin/swaymsg \"output * power off\"' \\\n "
474 ;; Resume + sleep.
475 "resume '" #$sway "/bin/swaymsg \"output * power on\"' \\\n "
476 "before-sleep '" #$swaylock "/bin/swaylock -f -c 000000'")))
477
478
479;;;
480;;; Serialization functions.
481;;;
482
483;; The main serialization code is defined in `sway-configuration->file' below.
484;; In this function, the configuration is seen as a list of lines and blocks.
485;;
486;; The other serialization functions of this files are helpers that will build
487;; the above list. Each function either returns a list, or elements that will
488;; be put in one. The elements of these lists will either be:
489;; - strings,
490;; In this case, the string is seen as a line to add to the configuraiton
491;; file.
492;; - a pair (cons 'begin-block string),
493;; In this case, a line "string {" is added to the configuration file, and
494;; the indentation level is increased by four.
495;; - the symbol 'end-block.
496;; In which case the indentation level is decreased by four, and the current
497;; configuration block is closed (with the line "}").
498
499;; A few helper functions:
500
501(define* (add-line-if field value
502 #:key (serializer %unset-value)
503 (suffix %unset-value))
504 (if (eq? %unset-value value)
505 %unset-value
506 #~(string-append #$field " "
507 #$(if (eq? serializer %unset-value)
508 value
509 (serializer value))
510 #$(if (eq? suffix %unset-value)
511 ""
512 suffix))))
513
514(define (add-block name content)
515 (let ((content (filter
516 (lambda (elt) (not (eq? elt %unset-value)))
517 content)))
518 (if (equal? content '())
519 '()
520 (append
521 (list #~(cons 'begin-block #$name))
522 content
523 (list #~'end-block)))))
524
525(define-syntax add-block*
526 (syntax-rules ()
527 ((add-block* name elt ...)
528 (add-block name (append elt ...)))))
529
530;; Serialization functions:
531
532(define (box str)
533 (let* ((len (string-length str))
534 (line (make-string (+ 8 len) #\#)))
535 (list
536 line
537 (string-append "### " str " ###")
538 line)))
539
540(define (with-heading str lst)
541 (define (heading str)
542 (let* ((len (string-length str))
543 (line (make-string (+ 2 len) #\#)))
544 (list
545 "" ;add an empty line before the configuration section.
546 (string-append "# " str)
547 line)))
548 (if (equal? lst '())
549 '() ;if the configuration block is empty, do not add the heading.
550 (append (heading str) lst)))
551
552(define-inlinable (serialize-boolean-yn b)
553 (if b "yes" "no"))
554(define-inlinable (serialize-boolean-ed b)
555 (if b "enable" "disable"))
556
557(define-inlinable (serialize-binding binder key value)
558 #~(string-append #$binder #$key " " #$value))
559
560(define (serialize-mouse-binding var)
561 (let* ((ev (car var))
562 (ev-code (number->string ev))
563 (command (cdr var)))
564 (serialize-binding "bindcode " ev-code command)))
565
566(define (serialize-keybinding var)
567 (let ((name (symbol->string (car var)))
568 (value (cdr var)))
569 (serialize-binding "bindsym " name value)))
570
571(define (serialize-gesture var)
572 (let ((name (symbol->string (car var)))
573 (value (cdr var)))
574 (serialize-binding "bindgesture " name value)))
575
576(define (serialize-variable var)
577 (let ((name (symbol->string (car var)))
578 (value (cdr var)))
579 (serialize-binding "set $" name value)))
580
581(define (serialize-exec b)
582 (if b
583 (lambda (exe)
584 #~(string-append "exec_always " #$exe))
585 (lambda (exe)
586 #~(string-append "exec " #$exe))))
587
588(define (serialize-output out)
589 (let* ((pre-ident (sway-output-identifier out))
590 (ident (if (symbol? pre-ident)
591 (symbol->string pre-ident)
592 (string-append "\"" pre-ident "\"")))
593 (background (let ((bg (sway-output-background out)))
594 (if (pair? bg)
595 bg
596 (cons bg 'fill))))
597 (resolution (sway-output-resolution out))
598 (position (sway-output-position out))
599 (extra-content (sway-output-extra-content out)))
600 (add-block
601 (string-append "output " ident)
602 (cons*
603 ;; Optional elements.
604 (add-line-if "bg" (car background)
605 #:suffix
606 (string-append " " (symbol->string (cdr background))))
607 (add-line-if "resolution" resolution)
608 (add-line-if "position" position
609 #:serializer
610 (lambda (p)
611 (string-append (number->string (point-x p))
612 " "
613 (number->string (point-y p)))))
614 ;; Extra-content: inlined as-is.
615 extra-content))))
616
617(define (serialize-input input)
618 (define-inlinable (fetch-arg layout acc)
619 (if (eq? layout %unset-value)
620 %unset-value
621 (acc layout)))
622
623 (define-inlinable (unfalse f)
624 (lambda (arg)
625 (let ((res (f arg)))
626 (if res res %unset-value))))
627
628 (define-inlinable (unnil f)
629 (lambda (arg)
630 (let ((res (f arg)))
631 (if (nil? res) %unset-value res))))
632
633 (let* ((pre-ident (sway-input-identifier input))
634 (ident (if (symbol? pre-ident)
635 (symbol->string pre-ident)
636 (string-append "\"" pre-ident "\"")))
637
638 ;; unpack the `layout' field.
639 (layout (sway-input-layout input))
640 (xkb-layout (fetch-arg layout keyboard-layout-name))
641 (xkb-variant (fetch-arg layout (unfalse keyboard-layout-variant)))
642 (xkb-model (fetch-arg layout (unfalse keyboard-layout-model)))
643 (xkb-options (fetch-arg layout (unnil keyboard-layout-options)))
644
645 (tap (sway-input-tap input))
646 (dwt (sway-input-disable-while-typing input))
647 (dwtp (sway-input-disable-while-trackpointing input))
648 (extra-content (sway-input-extra-content input)))
649 (add-block
650 (string-append "input " ident)
651 (cons*
652 ;; Optional.
653 (add-line-if "xkb_layout" xkb-layout)
654 (add-line-if "xkb_model" xkb-model)
655 (add-line-if "xkb_variant" xkb-variant)
656 (add-line-if "xkb_options" xkb-options
657 #:serializer (lambda (l) (string-join l ",")))
658 (add-line-if "dwt" dwt
659 #:serializer serialize-boolean-ed)
660 (add-line-if "dwtp" dwtp
661 #:serializer serialize-boolean-ed)
662 (add-line-if "tap" tap
663 #:serializer serialize-boolean-ed)
664 ;; extra-content inlined as-is.
665 extra-content))))
666
667(define (serialize-colors colors)
668 (define (border-serializer val)
669 (string-append (sway-border-color-border val)
670 " " (sway-border-color-background val)
671 " " (sway-border-color-text val)))
672 (if (eq? %unset-value colors)
673 '()
674 (let ((background (sway-color-background colors))
675 (statusline (sway-color-statusline colors))
676 (focused-background (sway-color-focused-background colors))
677 (focused-statusline (sway-color-focused-statusline colors))
678 (focused-workspace (sway-color-focused-workspace colors))
679 (active-workspace (sway-color-active-workspace colors))
680 (inactive-workspace (sway-color-inactive-workspace colors))
681 (urgent-workspace (sway-color-urgent-workspace colors))
682 (binding-mode (sway-color-binding-mode colors)))
683 (add-block
684 "colors"
685 (list
686 (add-line-if "background" background)
687 (add-line-if "statusline" statusline)
688 (add-line-if "focused_background" focused-background)
689 (add-line-if "focused_statusline" focused-statusline)
690 (add-line-if "focused_workspace" focused-workspace
691 #:serializer border-serializer)
692 (add-line-if "active_workspace" active-workspace
693 #:serializer border-serializer)
694 (add-line-if "inactive_workspace" inactive-workspace
695 #:serializer border-serializer)
696 (add-line-if "urgent_workspace" urgent-workspace
697 #:serializer border-serializer)
698 (add-line-if "binding_mode" binding-mode
699 #:serializer border-serializer))))))
700
701(define (serialize-mode mode)
702 (let ((name (sway-mode-mode-name mode))
703 (keys (sway-mode-keybindings mode))
704 (clicks (sway-mode-mouse-bindings mode)))
705 (add-block*
706 (string-append "mode \"" name "\"")
707 (map serialize-keybinding keys)
708 (map serialize-mouse-binding clicks))))
709
710(define (serialize-bar bar)
711 (define serialize-symbol
712 symbol->string)
713
714 (let ((identifier (symbol->string (sway-bar-identifier bar)))
715 (position (sway-bar-position bar))
716 (hidden-state (sway-bar-hidden-state bar))
717 (status-command (sway-bar-status-command bar))
718 (binding-mode-indicator (sway-bar-binding-mode-indicator bar))
719 (mouse-bindings (sway-bar-mouse-bindings bar))
720 (extra-content (sway-bar-extra-content bar))
721 (colors (sway-bar-colors bar)))
722 (add-block*
723 (string-append "bar " identifier)
724
725 (if (eq? colors %unset-value)
726 '()
727 (serialize-colors colors))
728 (list
729 (add-line-if "position" position
730 #:serializer serialize-symbol)
731 (add-line-if "hidden_state" hidden-state
732 #:serializer serialize-symbol)
733 (add-line-if "status_command" status-command)
734 (add-line-if "binding_mode_indicator" binding-mode-indicator
735 #:serializer serialize-boolean-yn))
736 ;; Mouse-bindings and extra-content
737 (map serialize-mouse-binding mouse-bindings)
738 extra-content)))
739
740(define (sway-configuration->file conf)
741 (let* ((extra (sway-configuration-extra-content conf))
742 (bar (sway-configuration-bar conf)))
743 (computed-file
744 "sway-config"
745 #~(begin
746 (use-modules (ice-9 format) (ice-9 match)
747 (srfi srfi-1))
748
749 (call-with-output-file #$output
750 (lambda (port)
751
752 ;; Add the (indented) line "s" to the output file.
753 (define (line s)
754 (lambda (i)
755 (format port "~a~a~%" i s)
756 i))
757
758 ;; Begin a block "name" and adjust the indentation.
759 (define (begin-block name)
760 (lambda (i)
761 (format port "~a~a {~%" i name)
762 (string-append " " i)))
763
764 ;; Ends an open block and adjust the indentation.
765 ;; Note: we must currently be in a configuration block.
766 ;; Otherwise, `string-drop' might fail.
767 (define (end-block)
768 (lambda (i)
769 (let ((i (string-drop i 4)))
770 (format port "~a}~%" i)
771 i)))
772
773 ;; Helper function. The configuration is represented as a list
774 ;; of actions (alter the indentation level, add a line, ...).
775 ;; This function recognises the action and calls the right
776 ;; function among those defined above.
777 (define (serializer-dispatch-m arg)
778 (match arg
779 ;; Special cases:
780 (('begin-block . str) (begin-block str))
781 ('end-block (end-block))
782 ;; Default case: `arg' is assumed to be a string.
783 (_ (line arg))))
784
785 (define (serializer-dispatch elt i)
786 ((serializer-dispatch-m elt) i))
787
788 (fold
789 ;; Dispatch function: depending on its argument, it will change
790 ;; the indentation level or add a line to the output file.
791 serializer-dispatch
792
793 ;; Initial indentation string. This string is prepended to
794 ;; lines before their serialization.
795 ""
796 ;; List of lines or indentation modifiers.
797 (list
798 ;; Header.
799 #$@(box "Auto-generated configuration")
800 "# DO NOT EDIT MANUALLY."
801
802 ;; Variables.
803 #$@(with-heading "Variables."
804 (map serialize-variable
805 (sway-configuration-variables conf)))
806
807 ;; Outputs.
808 #$@(with-heading "Outputs."
809 (flatmap serialize-output
810 (sway-configuration-outputs conf)))
811
812 ;; Inputs.
813 #$@(with-heading "Inputs."
814 (flatmap serialize-input
815 (sway-configuration-inputs conf)))
816
817 ;; Bar configuration:
818 ;; If the bar is unset, do not include anything.
819 #$@(if (eq? bar %unset-value)
820 '()
821 (with-heading "Bar configuration."
822 (serialize-bar bar)))
823
824 ;; Keybindings.
825 #$@(with-heading "Keybindings."
826 (map serialize-keybinding
827 (sway-configuration-keybindings conf)))
828 ;; Gestures.
829 #$@(with-heading "Gestures."
830 (map serialize-gesture
831 (sway-configuration-gestures conf)))
832
833 ;; Modes.
834 #$@(with-heading "Modes."
835 (flatmap serialize-mode
836 (sway-configuration-modes conf)))
837
838 ;; Startup-Programs.
839 #$@(with-heading
840 "Programs to execute (at startup)."
841 (map (serialize-exec #f)
842 (sway-configuration-startup-programs conf)))
843 ;; startup+reload-programs.
844 #$@(with-heading
845 "Programs to execute (at startup & after reload)."
846 (map (serialize-exec #t)
847 (sway-configuration-startup+reload-programs conf)))
848
849 ;; Extra-content.
850 #$@(with-heading "Extra-content" extra)))))))))
851
852
853;;;
854;;; Definition of the Home Service.
855;;;
856
857(define (sway-configuration->files sway-conf)
858 `((".config/sway/config" ,(sway-configuration->file sway-conf))))
859
860(define home-sway-service-type
861 (service-type
862 (name 'home-sway-config)
863 (extensions
864 (list (service-extension home-files-service-type
865 sway-configuration->files)
866 (service-extension home-profile-service-type
867 sway-configuration-packages)))
868 (description "Configure Sway by providing a file
869@file{~/.config/sway/config}.")
870 (default-value (sway-configuration))))
diff --git a/gnu/local.mk b/gnu/local.mk
index 46a687c28eb..90e22f15675 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -114,6 +114,7 @@ GNU_SYSTEM_MODULES = \
114 %D%/home/services/shepherd.scm \ 114 %D%/home/services/shepherd.scm \
115 %D%/home/services/sound.scm \ 115 %D%/home/services/sound.scm \
116 %D%/home/services/ssh.scm \ 116 %D%/home/services/ssh.scm \
117 %D%/home/services/sway.scm \
117 %D%/home/services/syncthing.scm \ 118 %D%/home/services/syncthing.scm \
118 %D%/home/services/mcron.scm \ 119 %D%/home/services/mcron.scm \
119 %D%/home/services/utils.scm \ 120 %D%/home/services/utils.scm \